components icon indicating copy to clipboard operation
components copied to clipboard

mat-form-field does not remove mat-form-field-invalid class on FormGroup reset

Open Nathan-Ryan opened this issue 8 years ago • 69 comments

Bug, feature request, or proposal:

Bug

What is the expected behavior?

Upon resetting a FormGroup, I would expect the visual state of the form to be reset also.

What is the current behavior?

The form group and controls are reset but the mat-input-invalid class remains on the md-input-container suggesting that the control is invalid.

What are the steps to reproduce?

This only seems to happen when the [formGroup] attribute is on a form tag. Works as expected on a div tag.

Create component with a FormGroup and a FormControl with Validators.required . Create a form tag with the [formGroup] attribute. Add an input control to the form with a required attribute.

When running, fill out the form so its valid, then reset the form and model through the click handler on a button. The required control will now have the mat-input-invalid class.

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

Angular 4.0.1 Material 2.0.0-beta.3 Windows 10 Chrome 57

Nathan-Ryan avatar Apr 21 '17 00:04 Nathan-Ryan

Have the same issue 😢

kurpav avatar Apr 22 '17 15:04 kurpav

plunker repro: http://plnkr.co/edit/UguaoP1sTR85pyZLh2TN?p=preview

mmalerba avatar May 10 '17 23:05 mmalerba

It looks like this is just a matter of putting type="reset" on your button. Without it, the form is marked as submitted which causes the error styling to show up. see: http://plnkr.co/edit/IUhbPom8FnauivHUW3bU?p=preview

mmalerba avatar May 11 '17 00:05 mmalerba

@mmalerba trying to understand how this would fix the issue for a button already type="submit".

I'm resetting after the form is submitted and a response has been received back from the server in an observable complete block.

i.e., submitForm() .subscribe( res => store.dispatch(type: foo, res), e => log(e), () => form.reset()); <- still leaving the form inputs as invalid

goelinsights avatar May 12 '17 01:05 goelinsights

@goelinsights sounds like maybe a forms issue (could be related to https://github.com/angular/angular/issues/15741). The md-input-container logic is correct, so there's nothing for material to do here

mmalerba avatar May 12 '17 16:05 mmalerba

Not sure why, using resetForm() method fixed this issue for me.

ghost avatar May 12 '17 17:05 ghost

@mmalerba not sure i agree with your diagnosis. I am experiencing same issues and have only updated from material-beta2 to material-beta3. Main angular libraries remain unchanged and problem has only been introduced since material upgrade.

It looks like this is just a matter of putting type="reset" on your button. Without it, the form is marked as submitted which causes the error styling to show up.

after form is submitted, error styling should definitely be removed.

zpydee avatar May 13 '17 11:05 zpydee

@mmalerba Why is this issue closed? The problem still exists when reseting the formGroup like explained by @goelinsights

Scenario: Press submit button Do some stuff with the data Then call formGroup.reset()

formGroup.reset() does NOT remove mat-input-invalid class screen shot 2017-05-30 at 4 06 33 pm

jeroenvanagt avatar May 30 '17 14:05 jeroenvanagt

@jeroenvanagt try this

<form [formGroup]="myFormGroup" #f="ngForm">
  ...
</form>
@ViewChild('f') myNgForm;

reset() {
  this.myNgForm.resetForm();
}

http://plnkr.co/edit/sRCiYvRqGevK493w79A4?p=preview

willshowell avatar May 30 '17 22:05 willshowell

@willshowell,

I understand that a reset button works. However, in my case I want to use a submit button, send the data to the backend server and then reset the form (so a new invite can be created).

For the reset, I use : this.form.reset() where form is a formGroup

jeroenvanagt avatar May 31 '17 07:05 jeroenvanagt

I now use the following workaround

        this.form.reset()

        Object.keys(this.form.controls).forEach(key => {
          this.form.controls[key].setErrors(null)
        });

jeroenvanagt avatar May 31 '17 08:05 jeroenvanagt

@jeroenvanagt Error state is calculated like this:

isInvalid && (isTouched || isSubmitted)

Unfortunately, resetting the FormGroup isn't enough. You'll need to reset the submitted state of the actual form.

To do that, you need to get access to the FormGroupDirective which binds the FormGroup to the form and then call resetForm() instead of reset().

<form [formGroup]="fg">
  ...
</form>
@ViewChild(FormGroupDirective) myForm;

sendDataToBackendAndResetForm() {
  // TODO: send data to backend
  if (this.myForm) {
    this.myForm.resetForm();
  }
}

See this updated plunker for an example

willshowell avatar May 31 '17 15:05 willshowell

@mmalerba I don't think we can call a workaround a resolution. This still is not fixed.

Why can't the FormGroup.reset() method use the FormGroupDirective to clear the submitted state of the form element?

Nathan-Ryan avatar Jun 16 '17 01:06 Nathan-Ryan

@Nathan-Ryan The FormGroup and FormGroupDirective are part of angular core, not angular material. If you want to request changes to the behavior you can file an issue with https://github.com/angular/angular

mmalerba avatar Jun 21 '17 19:06 mmalerba

@mmalerba the hacky workaround is just to manually remove .mat-input-invalid on submission. If that's the desired approach, we should put it into the docs as it's a fairly straightforward way to address what should be a common problem for a reusable form that is reset on submission (that from my perspective isn't an expected or obvious output).

On Wed, Jun 21, 2017 at 12:01 PM, mmalerba [email protected] wrote:

@Nathan-Ryan https://github.com/nathan-ryan The FormGroup and FormGroupDirective are part of angular core, not angular material. If you want to request changes to the behavior you can file an issue with https://github.com/angular/angular

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/angular/material2/issues/4190#issuecomment-310174269, or mute the thread https://github.com/notifications/unsubscribe-auth/ACv1DSsUuegP-lRLkdGOj5o1CoY8DEAUks5sGWh_gaJpZM4NDvLu .

--


Vijay Goel, M.D. Principal, Goel Insights 310-492-5601 www.goelinsights.com

goelinsights avatar Jun 27 '17 18:06 goelinsights

@goelinsights I may be mistaken but manually removing classes is not the recommended workaround. I'll summarize here:

  1. Submitted state is based on the FormGroupDirective or the NgForm (depending on if you're using template- or model-driven forms). FormGroup does not hold submitted state.

  2. If you wish to reset the form, you must gain access to the FormGroupDirective or the NgForm and call resetForm() on it. That will remove .mat-input-invalid from the input and all associated md-errors

  3. This behavior is in Angular core, not material. You are welcome to propose a change to the behavior, but that should be done in the angular core repository, not here.

  4. If you simply don't want .mat-input-invalid to depend at all on submitted state, you will be able to purpose https://github.com/angular/material2/pull/4750 for that once it lands.

willshowell avatar Jun 27 '17 21:06 willshowell

Any Update on this fix?

gersonpineda avatar Nov 21 '17 04:11 gersonpineda

The simplest solution isn't resetting the form afterwards, but preventing the form from being submitted in the first place. You can do that by putting a type="button" on the button element, so something like this works as expected in my project:

<button type="button" mat-raised-button (click)="form.reset()">
    reset
</button>

biowaffeln avatar Nov 28 '17 15:11 biowaffeln

this resolved my issue https://stackoverflow.com/questions/48216330/angular-5-formgroup-reset-doesnt-reset-validators

NJJ2 avatar Mar 13 '18 05:03 NJJ2

I think @biowaffeln's answer is the way to go. Simply avoid all references to "Submit" and you're good. To expand on his example:

Before:

<form [formGroup]="createForm" class="create-form" (ngSubmit)="submitForm()">
  <button type="submit" mat-raised-button color="primary" [disabled]="createForm.pristine">Create</button>
</form>

After:

<form [formGroup]="createForm" class="create-form">
  <button (click)="submitForm()" type="button" mat-raised-button color="primary" [disabled]="createForm.pristine">Create</button>
</form>

Your submit function doesn't accept any arguments, it will simply access form values via the class property, so it doesn't make a difference either way:

submitForm() {
  this.myEventEmitter.emit(this.createForm.value)
}

jplew avatar May 15 '18 23:05 jplew

@jplew an advantage of using (ngSubmit) on form is that the form is automatically submitted when you press Enter in a text field. You would need to do that manually.

ondrejpar avatar Jun 20 '18 18:06 ondrejpar

@NaveenJayaram94 created an infinite loop

chachan avatar Aug 29 '18 18:08 chachan

Actually this is still a bug only in material. It has nothing to do with resetting the submit state.

In angular core i can put markAsPristine and markAsUntouched on a single formControl. The css classes get set correctly ignoring if it was submitted or not.

The question is why put css class mat-form-field-invalid on it, when there is already ng-invalid. The "red-state" could be calculated like this: ng-invalid && ng-touched finish, it would work.

nickwinger avatar Nov 27 '18 12:11 nickwinger

Bug, feature request, or proposal:

Bug

What is the expected behavior?

Upon resetting a FormGroup, I would expect the visual state of the form to be reset also.

What is the current behavior?

The form group and controls are reset but the mat-input-invalid class remains on the md-input-container suggesting that the control is invalid.

What are the steps to reproduce?

This only seems to happen when the [formGroup] attribute is on a form tag. Works as expected on a div tag.

Create component with a FormGroup and a FormControl with Validators.required . Create a form tag with the [formGroup] attribute. Add an input control to the form with a required attribute.

When running, fill out the form so its valid, then reset the form and model through the click handler on a button. The required control will now have the mat-input-invalid class.

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

Angular 4.0.1 Material 2.0.0-beta.3 Windows 10 Chrome 57

I am also having this issue after reset the form controls are reset but mat-errors are showing invalid

krmgopi avatar Dec 03 '18 10:12 krmgopi

There could be some change detection issue with the mat-form-field-invalid class. I'll reopen for investigation

mmalerba avatar Dec 03 '18 17:12 mmalerba

Will the problem be solved in the next 1 - 2 releases? Since the problem already exists since 2017?

christophschoeni avatar Jan 30 '19 11:01 christophschoeni

bump

eugensunic avatar Jan 31 '19 11:01 eugensunic

I love the "not my department" attitude here. The workaround mentioned in this stackoverflow answer should be the default behavior

https://stackoverflow.com/questions/48216330/angular-5-formgroup-reset-doesnt-reset-validators

ctilley83 avatar Feb 02 '19 05:02 ctilley83

Versions: "@angular/animations": "^7.2.2", "@angular/cdk": "^7.3.2", "@angular/common": "^7.2.4", "@angular/compiler": "^7.2.4", "@angular/core": "^7.2.4", "@angular/forms": "^7.2.4", "@angular/material": "^7.3.2"

This work for me, for this scenario; I have and material stepper and the user can start de process if he likes, then before show the first step I reset de form calling form():

template: <form [formGroup]="formGroup"> <button type="button" (click)="submitForm()">

ts: ngOnInit() {this.formGroup = this._formBuilder.group(new MyForm()); }

submitForm() { let control: AbstractControl = null; Object.keys(this.formGroup.controls).forEach((name) => { control = this.formGroup.controls[name]; control.updateValueAndValidity(); }); }

reset() { let control: AbstractControl = null; this.formGroup.reset(new DatosGeneralesForm());

  setTimeout(() => {
    this.formGroup.markAsUntouched();
    Object.keys(this.formGroup.controls).forEach((name) => {
      control = this.formGroup.controls[name];
      control.reset();
      control.setErrors(null);
    });
  }, 100);

}

ccamba avatar Feb 28 '19 17:02 ccamba

it seems this is still an issue.

the workaround from @willshowell worked for me, but had to go through some research to get this fixed. Thinking it could be fixed with alternatives already provided here, or at least better documented.

bruno-kremer avatar Mar 11 '19 00:03 bruno-kremer