question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Strange mat-error & state behaviour on Custom ControlValueAccessor component

See original GitHub issue

Bug

I have this custom input component, using ControlValueAccessor and it is perfectly in sync with the controlling formGroup, and gives the valid, invalid, touched and hasErrors('required') to the formGroup & internally correctly.

What is the current behavior?

Whenever i want to use the mat-error component, it will only work as expected when I give the required attribute to the input. When I leave that out, the mat-error will never show, whatever I try. So on blur (touched=true) it will not show the mat-error. But it does in this simple plunkr: https://plnkr.co/edit/cJFCUITMlcBc78v06937?p=preview

I’m not sure why this is, the only thing I can think of is that I use [(ngModel)]="_value" on the input i.c.w. NG_VALUE_ACCESSOR/ControlValueAccessor, but I would think that since the formGroup state is correct, and it all works perfectly when having the required property on it, this should be irrelevant.

Looking at this @crisbeto’s answer: https://github.com/angular/material2/issues/4027 Point 1 seems to be saying a similar thing, that setting required on it, it works, and towards the end @willshowell states Errors are hidden until the input is both invalid and touched yet they are both invalid and when touched still don’t show it.

What is the expected behavior?

I would expect the required to not be relevant to showing the mat-error element. For example, I might want to validate an email with Validators.email but have it optional.

What are the steps to reproduce?

This plunkr demonstrates it by simply clicking and blurring each input field: https://plnkr.co/edit/4B2OOc5Spv9ewxbeIndZ?p=preview

Although While recreating it in plunkr, I found out some new strange behaviour. The first instance of the component doesn’t seem to apply the placeholder attribute, and also doesn’t change the touched state; however this problem has not occurred on my project (yet). See: https://plnkr.co/edit/FODeH4ZhE7IG01dmYCiR?p=preview This does indicate something strange going on, and I cannot figure out what it is.

What is the use-case or motivation for changing an existing behavior?

I would expect required not to be required for mat-error to work.

Which versions of Angular, Material, OS, TypeScript, browsers are affected?

Is there anything else we should know?

  • I’ve spent hours trying to fix this and trying to figure out why this happens. I’m pretty convinced it is a problem with the implementation of mat-error.
  • I’ve tried transcluding the mat-error like: <mat-error error>{{ getError() }}</mat-error> and then <ng-content select="[error]"></ng-content> But then it is placed wrongly and will always show the error, probably would not fix this issue either.
  • I’ve tried accessing the state internally on the component, with Injector & NgControl and subscribing to statusChanges and could see the internal status is correct as well.

Issue Analytics

  • State:open
  • Created 6 years ago
  • Reactions:2
  • Comments:16 (4 by maintainers)

github_iconTop GitHub Comments

6reactions
tonysampericommented, Mar 13, 2018

I solved by updating the errorState on the custom MatFormFieldControl.

Since my custom field is a formGroup made of 2 inputs I had to manually set the touched

setTouched(): void {
        this.parts.markAsTouched();
        this.validate(this.parts);
        //Updates errorState to show mat-error
        this.errorState = this.parts.invalid;
       //Emit stateChange to update value in mat-form-field
       this.stateChanges.next();
}

I call this function when either input is focused

EDIT

There was also a problem with the reset and errors won’t be reset. To solve, call yourFormControlOrGroup.reset() as first in the write method

writeValue(value: UbiTime): void {
     this.parts.reset();
     let newValue = {hours: "", minutes: ""};
     if (!!value && value instanceof UbiTime) {
          newValue = value;
     }
     this.parts.setValue(newValue);
     this._handlePropagation();
}
1reaction
benelliottcommented, Oct 25, 2017

@mxchange What I mean is that the mat-error in ui-autocomplete.html will respond only to the validity of the search input (the one it is a sibling of in a mat-form-field). It is bound to this element and not to your outer component. Thus it will only show when the search input has an error. The search input only has an error when empty if it is marked as required.

The “works without required” example you provided actually does have the required validator active, but it is active in the controller rather than the template because it is an example of reactive rather than template-driven forms. Note the formControlName="email" in the template which links the input to email: ['', [Validators.required] ] in the controller, which had the required validator enabled.

Read more comments on GitHub >

github_iconTop Results From Across the Web

mat-error not showing up with ControlValueAccessor
I have a custom app-input component which uses mat-form-field and mat-error but the error is not showing up.
Read more >
Best practice of wrapping material components : r/Angular2
Hi guys,I'm currently trying to wrap material components for the sole ... and pass that FormControl to my custom ControlValueAccessor.
Read more >
Angular Material: mat-error with custom ControlValueAccessor
It has a nice functionality to show errors on mat-form-field components, if their state is invalid, by using mat-error .
Read more >
Aug 08 2019 12:47 UTC - angular/angular - Gitter
I want to have a nested form which is managed by reactive form controllers. A component in the form does not contain normal...
Read more >
Input | Angular Material
UI component infrastructure and Material Design components for mobile and desktop Angular web applications.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found