Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular Material: Reseting reactiveform shows validation error

I am using angular5 reactivemodule to show a form in my application. I had also used required validator which will subsequently make the field in red color and show an error msg to the user.

It is working as expected but when I reset the form using

this.form.reset()

the form shows me a validation error that the specific field is required. I also used form.markAsPristine() or form.markAsUntouched() to make it work but the problem persist after applying multiple combination of possible pairs.

example.html

<form [formGroup]="checkForm" (ngSubmit)="submitForm()">
  <mat-form-field>
    <input matInput formControlName="name" placeholder="name" />
    <mat-error *ngIf="checkForm.get('name').errors?.required">
      Name is required.
    </mat-error>
  </mat-form-field>
  <mat-form-field>
    <input matInput formControlName="email" placeholder="email" />
    <mat-error *ngIf="checkForm.get('email').errors?.required">
      Name is required.
    </mat-error>
  </mat-form-field>
  <button [disabled]="checkForm.invalid" type="submit">add</button>
</form>

example.ts

checkForm  = this.formBuilder.group({
  'name': ['', Validators.required],
  'email': ['', Validators.required]
});

submitForm() {
   this.checkForm.reset();
   // this.checkForm.markAsPristine();
   this.checkForm.markAsUntouched();      
}

Any help is appreciated.

like image 225
Ajay Avatar asked Apr 12 '18 04:04

Ajay


1 Answers

By default, Angular/Material watch formControl's error state not only by touched but also submitted status of the form, see below source code.

isErrorState(control: FormControl | null, form: FormGroupDirective | NgForm | null): boolean {
  return !!(control && control.invalid && (control.touched || (form && form.submitted)));
                                                                       ^^^^^^^^^^^^^^
}

For reason above, you also need to reset the form to unsubmitted status.


You can call resetForm of FormGroupDirective(getting instance by ViewChild) for it will reset both the form data and submit status.

<form #form="ngForm" [formGroup]="checkForm" (ngSubmit)="submitForm(form)">
  ...
</form>

@ViewChild('form') form;

submitForm() {
  this.form.resetForm();
  ...
}

You can also overwrite the default one via implementing ErrorStateMatcher with custom conditions such as ignore submitted status of the form, and apply it on material components.

<mat-form-field>
  <input matInput formControlName="name" placeholder="name" [errorStateMatcher]="errorMatcher" />
  <mat-error *ngIf="checkForm.get('name').errors?.required">
    Name is required.
  </mat-error>
</mat-form-field>

// define custom ErrorStateMatcher
export class CustomErrorStateMatcher implements ErrorStateMatcher {
  isErrorState(control: FormControl, form: NgForm | FormGroupDirective | null) {
    return control && control.invalid && control.touched;
  }
}

// component code
@Component({...})
export class CustomComponent {
  // create instance of custom ErrorStateMatcher
  errorMatcher = new CustomErrorStateMatcher();
}

see fixed demo.

like image 130
Pengyy Avatar answered Sep 17 '22 14:09

Pengyy