angular / components

Component infrastructure and Material Design components for Angular
https://material.angular.io
MIT License
24.32k stars 6.72k forks source link

Setting a single formControl to Untouched does not reset the error css state #14289

Open nickwinger opened 5 years ago

nickwinger commented 5 years ago

Bug, feature request, or proposal:

Bug

What is the expected behavior?

Don't use mat-form-field-invalid, but use the native angular core css classes ng-invalid Because mat-form-field-invalid does not get removed when setting a single formControl to untouched

What is the current behavior?

mat-form-field-invalid does not get removed when doing markAsUntouched

What are the steps to reproduce?

Providing a StackBlitz reproduction is the best way to share your issue.
StackBlitz starter: https://goo.gl/wwnhMV
On every simple form

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

Material uses it's own mat-form-field-invalid css class instead of the angular core css classes, this makes error. This is a wrong design

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

newest versions

Is there anything else we should know?

manklu commented 5 years ago

Works for me

https://angular-material2-issue-y4ehyx.stackblitz.io https://stackblitz.com/edit/angular-material2-issue-y4ehyx

manklu commented 5 years ago

btw

Material uses it's own mat-form-field-invalid css class instead of the angular core css classes, this makes error.

ng-invalid is independent of the touched state. It's set as soon as the validation fails.

nickwinger commented 5 years ago

Thank you for your example. You are right, i was not exact enough. I have edited the example and now it won't work: https://angular-material2-issue-ekspou.stackblitz.io

You have to put it inside a form with a ngSubmit, then hit enter (to submit). After that you cannot set the control to untouched no more... This seems to be a bug in material. However i still don't understand why material uses it's on invalid-css-class, when there is already from angular. (then they would not have to remove it...)

manklu commented 5 years ago

You have to put it inside a form with a ngSubmit, then hit enter (to submit). After that you cannot set the control to untouched no more...

You can, but after a submit, the error display is independent of the touched state. I have added a submit button to demonstrate it.

However i still don't understand why material uses it's on invalid-css-class, when there is already from angular. (then they would not have to remove it...)

I have added a simple form field and styling with ng-invalid. As you can see it's set before you do anything with the field.

https://angular-material2-issue-klreox.stackblitz.io https://stackblitz.com/edit/angular-material2-issue-klreox

karolkochan commented 5 years ago

I have experienced the same problem. You can dispatch two cases on stackblitz below:

  1. Focus field -> Blur -> (field is invalid) -> Hit "Reset" -> Field is valid again
  2. Focus field -> Blur -> (field is invalid) -> Hit "Submit" -> Hit "Reset" -> Field is invalid but should be valid ❗️

https://stackblitz.com/edit/angular-nlqln6

Does anyone have a clean solution for this behaviour? It drives me crazy.

maartentibau commented 5 years ago

@karolkochan there is a very easy solution for this, and that's putting a correct type on the button. If you just do <button type="reset" (click)="reset()">Reset form</button> it will just work fine.

I do agree that form.reset() doesn't work properly when I replay your scenario, but still... form.reset() is actually not really needed when you set type=reset on your button. The only thing I'm not 100% sure of if it works in all browsers.

karolkochan commented 5 years ago

@maartentibau thanks for your response but that's not my UI scenario since I don't have any "Reset" form button. My case is tab component with two tabs "Sign in | Register" and I want to reset form when switching between tabs, so I expected form.reset() to work as intended.

And yeah, maybe hidden <button type="reset">...</button> could deal with it but let's agree that it would be kind of a hack.

manklu commented 5 years ago

@karolkochan Programmatically you can call the resetForm method of the directive.

https://stackblitz.com/edit/angular-nlqln6-pgdfuh?file=app%2Fform-field-error-example.ts