web-dev-qa-db-fra.com

Angular 5 La réinitialisation du groupe de formulaires ne réinitialise pas les validateurs

J'ai un formulaire sur ma page et lorsque j'appelle FormGroup.reset(), la classe de formulaires est définie sur ng-pristine ng-untouched mais FormControl.hasError(...) renvoie toujours la vérité. Qu'est-ce que je fais mal ici?

Modèle

<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>

Composant

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/

42
efarley

Il (FormGroup) se comporte correctement. Votre formulaire nécessite un nom d'utilisateur et un mot de passe. Par conséquent, lorsque vous réinitialisez le formulaire, il doit être invalide (le formulaire sans nom d'utilisateur/mot de passe n'est pas valide).

Si je comprends bien, votre problème est que les erreurs en rouge ne sont pas présentes lors du premier chargement de la page (où le formulaire est AUSSI invalide), mais apparaissent lorsque vous cliquez sur le bouton. Ce problème est particulièrement important lorsque vous utilisez Material.

Autant que je sache, <mat-error> vérifie la validité de FormGroupDirective, pas FormGroup, et réinitialiser FormGroup ne réinitialise pas FormGroupDirective. C'est un peu gênant, mais pour effacer <mat-error>, vous devez également réinitialiser FormGroupDirective.

Pour ce faire, dans votre modèle, définissez une variable en tant que telle:

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

Et dans votre classe de composants, appelez formDirective.resetForm():

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

Problème GitHub: https://github.com/angular/material2/issues/419

86
Harry Ninh

Après avoir lu les commentaires c'est la bonne approche

// 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) ;
    });
}

Il n'y avait pas besoin d'appeler form.clearValidators()

12
Savio Rodrigues

En plus de la solution de Harry Ninh, si vous souhaitez accéder à formDirective dans votre composant sans avoir à sélectionner un bouton de formulaire, alors:

Modèle:

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

Composant:

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

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

  constructor(... )

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

J'avais aussi le même ensemble de problèmes. Mon problème était que j'utilisais mat-form-field et formGroup. Après avoir réinitialisé le formulaire, l’indicateur submitted n’était pas réinitialisé.

Donc, la solution qui a fonctionné pour moi est de mettre une directive de ngForm avec formGroup et de passer onSubmit(form). Ajout de @ViewChild('form') form; dans le composant, puis j'ai utilisé this.form.resetForm();

0
prisar

J'ai constaté qu'après avoir appelé resetForm () et reset (), les fichiers soumis n'étaient pas réinitialisés et restaient à l'état true, ce qui provoquait l'affichage de messages d'erreur. Cette solution a fonctionné pour moi. Je l'ai trouvé en cherchant une solution pour appeler select () et focus () sur une balise input, qui ne fonctionnait pas non plus comme prévu. Enveloppez simplement vos lignes dans un setTimeout (). C'est un peu un bidouillage, mais fait le tour.

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

La solution ci-dessous fonctionne pour moi lorsque j'essaie de réinitialiser un contrôleur de formulaire spécifique dans un groupe de formulaires -

 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();
0
Sayan Samanta