Skip to content

Strange mat-error & state behaviour on Custom ControlValueAccessor component #7920

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
mxchange opened this issue Oct 20, 2017 · 19 comments
Open
Labels
area: material/form-field P3 An issue that is relevant to core functions, but does not impede progress. Important, but not urgent

Comments

@mxchange
Copy link

mxchange commented Oct 20, 2017

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: #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?

  • "@angular/material": "2.0.0-beta.11",
  • "@angular/common": "^4.3.6",
  • "@angular/compiler": "^4.3.6",
  • "@angular/compiler-cli": "^4.3.6",
  • "@angular/core": "^4.3.6",
  • "@angular/forms": "^4.3.6",
  • "@angular/http": "^4.3.6",
  • "typescript": "^2.4.2",

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.
@benelliott
Copy link
Contributor

benelliott commented Oct 20, 2017

Maybe I am misunderstanding your issue, but is it not simply that the mat-error in ui-autocomplete.html is binding to your input (the one with [(ngModel)]="_value", which is itself only invalid if it has the required attribute? An empty value for this input will be valid otherwise, and no error will be shown.

@mxchange
Copy link
Author

mxchange commented Oct 22, 2017

@benelliott No, the formControl.valid property is false (or .invalid is true) whether it's required or not, So in either cases it should show. Take for example the same but with email: https://plnkr.co/edit/DxCg9mn40130yY6KNH3R?p=preview

Although I now see that that is not behaving as expected, and will only show the error when the field is empty, and required set. When I type in an incorrect email, it will still not show the error, whether I set required or not...

So now my question really becomes, How do I make the mat-error component show, when there is an error, and there is, but it's just now working correctly.

I think it must also be something with the implementation of this component, because The first instance will each time not show the placeholder property, and the options are somehow empty.

@mxchange mxchange changed the title mat-error not shown unless required attribute is set Strange mat-error behaviour on Custom ControlValueAccessor component Oct 22, 2017
@mxchange mxchange changed the title Strange mat-error behaviour on Custom ControlValueAccessor component Strange mat-error & state behaviour on Custom ControlValueAccessor component Oct 22, 2017
@benelliott
Copy link
Contributor

benelliott commented 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.

@mmalerba mmalerba added the P3 An issue that is relevant to core functions, but does not impede progress. Important, but not urgent label Nov 21, 2017
@mmalerba
Copy link
Contributor

@mxchange is this still an issue or were you able to resolve it?

updated plunker: https://plnkr.co/edit/zMrtVVmxi7O9Aej4gLl1?p=preview

@mxchange
Copy link
Author

mxchange commented Nov 23, 2017

@mmalerba not really, can you explain why the first input field is not showing the error, while it has the same required properties as the second one (in your updated plunker). And why the placeholder is not working? (It shows the default, as if it's not passing the variable...)

@ShawnTseng
Copy link

@mmalerba
When I use markAsTouched() to trigger the 'custom form field control', the mat-error doesn't show up.
The status is still on mat-hint.
I need to use mouse to click the 'custom form field control' for the mat-error. And I read the source code.
image
Maybe the problem is on this ngSwitch, could you help me to check this out?
Thank you very much.

@divyameher
Copy link

@mxchange Does this issue resolved for you?

@mxchange
Copy link
Author

@divyameher no

@benelliott
Copy link
Contributor

@mxchange Did you read my comment above? Is there something I misunderstood about your use case?

@tonysamperi
Copy link

I have the same issue with a custom form field...the error won't show

@tonysamperi
Copy link

tonysamperi commented 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();
}

@divyameher
Copy link

@tonysamperi So does your Custom form field is only compatible with FormGroup or will it also works with NgModel?

@tonysamperi
Copy link

@divyameher Works perfectly also with NgModel!

@nhducseuit
Copy link

nhducseuit commented Jul 26, 2018

@tonysamperi could you show a working example of your workaround? Sorry I get confused with some part of your code but my custom form field control also consists of inputs (3 inputs)

@tonysamperi
Copy link

@nhducseuit sorry, but I really can't prepare it right now...
I have to close some activities since I'll be on holiday in a couple days...

If you prepare a stackblitz maybe I can take a look...

@urdarinda
Copy link

Any updates on this?
No mat error shows if the field is not required but is invalid

@JayAhn2
Copy link

JayAhn2 commented Oct 10, 2023

It is still an issue.

@iErKy
Copy link

iErKy commented Nov 15, 2023

Hello, I have the same problem, I see this has been active since 2017, any idea or plan to fix this or anyone know a workaround to show the mat error when the form field is not required?

Thanks in advance.

@Cubelaster
Copy link

Also experiencing really similar issue.
I have a custom mat Autocomplete component which works properly if user touches it but programatically won't show mat-error.
Like, when I call form.markAllAsTouched() I clearly see all the required states change, my errorState implementation of MatFormFieldControl returns true but mat-error won't show.
If I move mat-error to outside of the custom component, it works.
Why would that be the case?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: material/form-field P3 An issue that is relevant to core functions, but does not impede progress. Important, but not urgent
Projects
None yet
Development

No branches or pull requests