What is the most effective way to approach resetting a reactive angular form?

2.8k Views Asked by At

I have Reactive Form using Angular Material inputs (mdInput) that is initialized in the following manner using FormBuilder:

contactForm: FormGroup;

this.contactForm = this.fb.group({
  name: ['', [Validators.required, Validators.maxLength(128)]],
  email: ['', [Validators.required, Validators.email]],
  subject: ['', [Validators.required, Validators.maxLength(128)]],
  message: ['', [Validators.required, Validators.maxLength(1000)]]
});

onSubmit(): void {
  this.resetForm();
}

private resetForm(): void {
  this.contactForm.reset();
}    

With Angular Material inputs associated to the respective FormControl elements with hooking into (ngSubmit):

<form [formGroup]="contactForm" (ngSubmit)="onSubmit()">
  <md-input-container>
    <input mdInput formControlName="name" placeholder="Name">
  </md-input-container>

  <button type="submit" md-raised-button [disabled]="contactForm.invalid">Submit</button>

When calling reset() on the FormGroup contactForm (this.contactForm.reset(), the form elements values are successfully cleared/replaced with empty strings, but the elements are both immediately dirty and touched with CSS classesng-invalid&&ng-touchedpresent on the elements. Strangely they also have theng-pristineCSS class on them after thereset()`.

What is the most effective way to approach resetting the form including clearing/resetting the FormControl values and marking them as not touched and not dirty? Is it utilizing markAsUntouched() or markAsPristine()? Is it using setValue() or reset() with specific options? The goal is to reset the form as if the user is interacting with it for the first time.

Update: Here is a Stackblitz showing this issue in action.

Thank you for any help you can provide.

1

There are 1 best solutions below

0
On BEST ANSWER

As mentioned by @Harry Ninh in the comments, using a regular button instead of ngSubmit will fix the behavior. This is because, by default, Material errors show when an input is invalid and either touched or submitted. There is a long thread about it here, but basically, calling reset() on a form control or form group does not reset the actual form, just the values.

You can do one of the following:

  1. Use the workaround mentioned by @Harry Ninh
  2. Use ViewChild to get access to the FormGroupDirective and reset it.

See here:

@ViewChild(FormGroupDirective) myForm;

contactForm: FormGroup;

constructor(private fb: FormBuilder) {
  this.createForm();
}

private createForm(): void {
  this.contactForm = this.fb.group({
    name: ['', [Validators.required, Validators.maxLength(128)]],
    email: ['', [Validators.required, Validators.email]],
    subject: ['', [Validators.required, Validators.maxLength(128)]],
    message: ['', [Validators.required, Validators.maxLength(1000)]]
  });
}

onSubmit(): void {
  this.resetForm();
}

private resetForm(): void {
  if (this.myForm) {
    this.myForm.resetForm();
  }
}