5

I am new to angular 6 ,Here I am trying to reset the form after submitting the data.

Everything works fine but when I reset the form after successful data submit to database it triggers all the required validators in the form.

I tried many ways to solve this but I couldn't solve it .

Here after each form submission I want to reset the form and all the validators before enter the data in form fields for another submission.

app.component.html

<form [formGroup]="newMemberForm" (submit)="CreateMember(newMemberForm.value)" novalidate>
....
....
</form>

app.component.ts

            this.newMemberForm = this.formBuilder.group({
                  M_Number: ['', [Validators.required]],
                  F_Number: ['', [Validators.required]],
                  M_Name: ['', [Validators.required, Validators.minLength(4)]],
                  M_Status: ['', [Validators.required]],
                  M_Dob: ['', [Validators.required]],
                  M_Sex: ['', [Validators.required]],

                });

       CreateMember(memberForm) { 
        this.dmlService.CreateNewMember(memberForm).subscribe(data => {
              if (data[0]['RESPONSE'] == 'TRUE') 
         {
         this.newMemberForm.reset();
        }
       });
}

Here I have reset the form it triggers the required validatord.If I clears all the validators inside the above function ,When I enter another form data the validations are not working.

Here I want to reset all the validator and form after each form submission and I want to submit next set of form data .

can anyone help me to solve this .

Zhu
  • 3,679
  • 14
  • 45
  • 76

3 Answers3

9

You would need to reset as below:

In your html:

<form [formGroup]="newMemberForm" #formDirective="ngForm"  
(submit)="CreateMember(newMemberForm.value,formDirective)" novalidate>

In .ts:

CreateMember(value,formDirective:FormGroupDirective){
 ...
 formDirective.resetForm();
 this.myForm.reset();
}

Material checks the validity of FormGroupDirective and not of FormGroup hence resetting FormGroup does not reset FormGroupDirective.

Issue reported here too: https://github.com/angular/material2/issues/9347

User3250
  • 2,961
  • 5
  • 29
  • 61
0

Thats great solution but, reactive forms have their own feature to do so.

You can remove validations on specific formGroup/formcontrol by using clearValidators() for reactive forms.

this.formGroup.clearValidators() or      
 this.formGroup.controls.controlName.clearValidators()

After this, you have to update form control with the removed validator

this.formGroup.controls.controlName.updateValueAndValidity()

This helped me to resolve same issue, hope it helps you too

Vivek Singh
  • 289
  • 1
  • 4
  • Unfortunately, when clearing validators, we need to add them again in order for them to work for subsequent inputs. By simply doing `controlName.clearValidators()` and `controlName.updateValueAndValidity()` the validators will be removed (at least since Angular 13). – ovichiro Jun 01 '22 at 12:24
0

As stated in answers here and here, with details in the official docs:

The problem is that FormGroup::reset() does not clear the submitted state which also triggers the validators with some ErrorStateMatchers.
The submitted state is tracked by a FormGroupDirective object. Use FormGroupDirective::resetForm() to clear it.
If you're using Angular Material, the default ErrorStateMatcher will check form.submitted in addition to control.invalid and control.touched.
So you have 2 options: get a reference to the directive and call resetForm(), or declare a custom ErrorStateMatcher that doesn't check for submitted state and use it on your inputs as shown in the docs.

Option 1:

@Component({
  selector: '...',
  templateUrl: '...',
  styleUrls: '...'
})
export class MyCustomComponent {

  @ViewChild(FormGroupDirective) formGroupRef: FormGroupDirective | undefined;  // <<----

  myInputFormControl = new FormControl('', [Validators.required]);
  myFormGroup: FormGroup;

  constructor(private fb: FormBuilder, private myService: MyService) {
    this.myFormGroup = this.fb.group({
      myInput: this.myInputFormControl
    });
  }

  onSubmit(): void {
    if (this.myFormGroup.valid) {
      let myData: MyData = {
        myInput: this.myInputFormControl.value;
      }

      // submit form to server
      this.myservice.submitData(myData).subscribe({
        next: (response) => {
          console.log('Data submitted successfully! Response: ', response);
          this.formGroupRef?.resetForm();               // <<----
        },
        error: (err) => {
          console.log("Errors while submitting data: ", err);
        }
      });
    }
  }
}
<form [formGroup]="myFormGroup" (submit)="onSubmit()">
  <input matInput type="text" [formControl]="myInputFormControl">
    <mat-error *ngIf="myInputFormControl.hasError('required')">
      Value is required
    </mat-error>
</form>

Option 2, custom ErrorStateMatcher:

/** Error when invalid control is touched */
export class MyErrorStateMatcher implements ErrorStateMatcher {
  isErrorState(control: FormControl | null, form: FormGroupDirective | NgForm | null): boolean {
    return !!(control && control.invalid && control.touched);
  }
}

@Component({
  selector: '...',
  templateUrl: '...',
  styleUrls: '...'
})
export class MyCustomComponent {

  myInputFormControl = new FormControl('', [Validators.required]);
  myFormGroup: FormGroup;

  myMatcher = new MyErrorStateMatcher();

  constructor(private fb: FormBuilder, private myService: MyService) {
    this.myFormGroup = this.fb.group({
      myInput: this.myInputFormControl
    });
  }

  onSubmit(): void {
    // submit form to server
    this.myFormGroup.reset();
  }
}
<form [formGroup]='myFormGroup' (submit)="onSubmit()">
  <input matInput type="text" [formControl]="myInputFormControl" [errorStateMatcher]="myMatcher">
    <mat-error *ngIf="myInputFormControl.hasError('required')">
      Value is required
    </mat-error>
</form>
ovichiro
  • 301
  • 3
  • 7