Angular 5 FormGroup reset doesn't reset validators

青春壹個敷衍的年華 提交于 2019-11-26 06:06:34

问题


I have a form on my page and when I call FormGroup.reset() it sets the forms class to ng-pristine ng-untouched but FormControl.hasError(...) still returns truthy. What am I doing wrong here?

Template

<form [formGroup]=\"myForm\" (ngSubmit)=\"submitForm(myForm)\">
  <mat-form-field>
    <input matInput formControlName=\"email\" />
    <mat-error *ngIf=\"email.hasError(\'required\')\">
      Email is a required feild
    </mat-error>
  </mat-form-field>
  <mat-form-field>
    <input matInput type=\"password\" formControlName=\"password\" />
    <mat-error *ngIf=\"password.hasError(\'required\')\">
      Password is a required feild
    </mat-error>
  </mat-form-field>
  <button type=\"submit\">Login</button>
</form>

Component

export class MyComponent {
  private myForm: FormGroup;
  private email: FormControl = new FormContorl(\'\', Validators.required);
  private password: FormControl = new FormControl(\'\', Validators.required);

  constructor(
    private formBuilder: FormBuilder
  ) {
    this.myForm = formBuilder.group({
      email: this.email,
      password: this.password
    });
  }

  private submitForm(formData: any): void {
    this.myForm.reset();
  }
}

Plunker

http://embed.plnkr.co/Hlivn4/


回答1:


It (FormGroup) behaves correctly. Your form requires username and password, thus when you reset the form it should be invalid (i.e. form with no username/password is not valid).

If I understand correctly, your issue here is why the red errors are not there at the first time you load the page (where the form is ALSO invalid) but pop up when you click the button. This issue is particularly prominent when you're using Material.

AFAIK, <mat-error> check the validity of FormGroupDirective, not FormGroup, and resetting FormGroup does not reset FormGroupDirective. It's a bit inconvenient, but to clear <mat-error> you would need to reset FormGroupDirective as well.

To do that, in your template, define a variable as such:

<form [formGroup]="myForm" #formDirective="ngForm" 
  (ngSubmit)="submitForm(myForm, formDirective)">

And in your component class, call formDirective.resetForm():

private submitForm(formData: any, formDirective: FormGroupDirective): void {
    formDirective.resetForm();
    this.myForm.reset();
}

GitHub issue: https://github.com/angular/material2/issues/4190




回答2:


After reading the comments this is the correct approach

// you can put this method in a module and reuse it as needed
resetForm(form: FormGroup) {

    form.reset();

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

There was no need to call form.clearValidators()




回答3:


In addition to Harry Ninh's solution, if you'd like to access the formDirective in your component without having to select a form button, then:

Template:

<form 
  ...
  #formDirective="ngForm" 
>

Component:

import { ViewChild, ... } from '@angular/core';
import { NgForm, ... } from '@angular/forms';

export class MyComponent {
 ...
 @ViewChild('formDirective') private formDirective: NgForm;

  constructor(... )

  private someFunction(): void { 
    ...
    formDirective.resetForm();
  }
}



回答4:


I found that after calling resetForm() and reset(), submitted was not being reset and remained as true, causing error messages to display. This solution worked for me. I found it while looking for a solution to calling select() and focus() on an input tag, which also wasn't working as expected. Just wrap your lines in a setTimeout(). I think setTimeout is forcing Angular to detect changes, but I could be wrong. It's a bit of a hack, but does the trick.

<form [formGroup]="myFormGroup" #myForm="ngForm">
    …
    <button mat-raised-button (click)="submitForm()">
</form>
submitForm() { 
    …
    setTimeout(() => {
        this.myForm.resetForm();
        this.myFormGroup.reset();
    }, 0);
}



回答5:


I was also having the same set of problems. My problem was that i was using mat-form-field and formGroup. After resetting the form submitted flag was not resetting.

So, the solution that worked for me is, putting a directive of ngForm along with formGroup and passing onSubmit(form). Added @ViewChild('form') form; in component and then I used this.form.resetForm();




回答6:


The below solution works for me when trying to reset specific form controller in form group -

 this.myForm.get('formCtrlName').reset();
 this.myForm.get('formCtrlName').setValidators([Validators.required, Validators.maxLength(45), Validators.minLength(4), Validators.pattern(environment.USER_NAME_REGEX)]);
 this.myForm.get('formCtrlName').updateValueAndValidity();



回答7:


Move the submit function from your form to your button and add types to your buttons:

<form [formGroup]="createForm">
  <button (click)="submitForm()" type="submit">Submit</button>
  <button (click)="createForm.reset()" type="reset">Reset</button>
</form>


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!