Angular 5 FormGroup Reset setzt Validatoren nicht zurück

75

Ich habe ein Formular auf meiner Seite und wenn ich FormGroup.reset()es aufrufe, setzt es die Formularklasse auf, gibt ng-pristine ng-untouchedaber FormControl.hasError(...)immer noch die Wahrheit zurück. Was mache ich hier falsch?

Vorlage

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

Komponente

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/

Efarley
quelle
1
Können Sie versuchen, auch anzurufen this.myForm.markAsUntouched();?
Explosion Pills
Das funktioniert nicht und sollte aufgrund der Dokumentation nicht notwendig sein. ( v2.angular.io/docs/ts/latest/api/forms/index/… )
Efarley

Antworten:

139

Es ( FormGroup) verhält sich korrekt. Ihr Formular erfordert Benutzername und Passwort. Wenn Sie das Formular zurücksetzen, sollte es ungültig sein (dh das Formular ohne Benutzername / Passwort ist ungültig).

Wenn ich das richtig verstehe, liegt Ihr Problem hier darin, dass die roten Fehler beim ersten Laden der Seite (wo das Formular AUCH ungültig ist) nicht vorhanden sind, sondern beim Klicken auf die Schaltfläche angezeigt werden. Dieses Problem tritt besonders häufig auf, wenn Sie Material verwenden.

AFAIK, <mat-error>überprüfen Sie die Gültigkeit von FormGroupDirective, nicht FormGroup, und das Zurücksetzen FormGroupwird nicht zurückgesetzt FormGroupDirective. Es ist ein bisschen unpraktisch, aber um zu löschen <mat-error>, müssten Sie auch zurücksetzen FormGroupDirective.

Definieren Sie dazu in Ihrer Vorlage eine Variable als solche:

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

Rufen Sie in Ihrer Komponentenklasse Folgendes auf formDirective.resetForm():

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

GitHub-Problem: https://github.com/angular/material2/issues/4190

Harry Ninh
quelle
Dieses Problem muss wirklich gelöst werden, wie Sie sagten, es ist ziemlich unpraktisch, diese Problemumgehung verwenden zu müssen ... Wird damit funktionieren, guter Fang und danke für die Lösung.
Schankam
1
In meinem Fall hatte ich eine sehr einzigartige Situation, in der ich das "Übermittelte" zurücksetzen musste, ohne die Formularwerte zu löschen (die resetForm ()) mit mir machte. Um das zu umgehen, habe ich es getan (<any>formDirective).submitted = false;. Eine Art schmutziger Hack, aber wenn man sich den Quellcode ansieht, gibt es keinen offensichtlichen Grund, der eingereicht werden muss, um nur in ihrer Typoskript-Definition gelesen zu werden.
Geißel192
2
Lesen Sie die Github-Ausgabe, in der die offizielle Antwort "nicht meine Abteilung" lautete. Ziemlich lahm, ich erwarte besser von Google-Mitarbeitern.
Ctilley79
Mit Winkel 7.2.2:Argument of type NgForm is not assignable to type FormGroupDirective
Msanford
1
Nach dem Testen mit vielen Lösungen funktioniert diese einfach perfekt !!
JP Bala Krishna
27

Nach dem Lesen der Kommentare ist dies der richtige Ansatz

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

Es war nicht nötig anzurufen form.clearValidators()

Savio Rodrigues
quelle
7
Dadurch werden die Validatoren einfach entfernt und nicht zurückgesetzt.
Maximillion Bartango
2
Um die Validatoren this.loginform.clearValidators () zu löschen, setzen Sie die Fehler des Steuerelements auf null
Jorge Valvert
funktioniert perfekt mit Angular 9. Etwas anderes stimmt nicht mbue
Petros Kyriakou
19

Wenn Sie zusätzlich zu Harry Ninhs Lösung auf die formDirective in Ihrer Komponente zugreifen möchten, ohne eine Formularschaltfläche auswählen zu müssen, gehen Sie wie folgt vor:

Vorlage:

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

Komponente:

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

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

  constructor(... )

  private someFunction(): void { 
    ...
    formDirective.resetForm();
  }
}
Maximillion Bartango
quelle
1
Ich denke, das ist eine bessere Antwort. Die als Antwort gekennzeichnete muss eine lokale lokale Variable an den Code dahinter übergeben, was nicht wünschenswert ist. Diese Antwort hat jedoch sehr gute Informationen darüber geliefert, wie Formulare funktionieren.
Sam
Für Angular 8 benötigt die Direktive `@ViewChild zwei Parameter. Der andere Parameter neben der Zeichenfolge 'formDirective' sind Metadateneigenschaften. Weitere Informationen finden Sie unter angle.io/api/core/ViewChild#description .
Jonathan Cardoz
Gute Antwort, aber er setzt nicht nur Validatoren zurück, sondern auch alle Werte (von Benutzern eingegeben) im Formular zurück.
Ukie
3

Die folgende Lösung funktioniert für mich, wenn ich versuche, einen bestimmten Formular-Controller in der Formulargruppe zurückzusetzen.

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

Ich stellte fest, dass nach dem Aufruf von resetForm () und reset () die Übermittlung nicht zurückgesetzt wurde und als wahr blieb, was dazu führte, dass Fehlermeldungen angezeigt wurden. Diese Lösung hat bei mir funktioniert. Ich fand es, als ich nach einer Lösung suchte, um select () und focus () für ein Eingabe-Tag aufzurufen, was ebenfalls nicht wie erwartet funktionierte. Wickeln Sie einfach Ihre Zeilen in ein setTimeout (). Ich denke, setTimeout zwingt Angular, Änderungen zu erkennen, aber ich könnte mich irren. Es ist ein bisschen ein Hack, aber macht den Trick.

<form [formGroup]="myFormGroup" #myForm="ngForm">
    …
    <button mat-raised-button (click)="submitForm()">
</form>
submitForm() { 
    …
    setTimeout(() => {
        this.myForm.resetForm();
        this.myFormGroup.reset();
    }, 0);
}
Henri Fournier
quelle
Ich habe diese Antwort gefunden, nachdem ich den ganzen Tag verbracht habe. setTimeout () half dabei, dieses Problem zu beheben. Wenn Sie eine Beschreibung hinzufügen können, wie dieser "Hack" funktioniert, ist dies hilfreich. Getestet mit Winkel 7.2.8
Rajendra Thorat
1

Fügen Sie die Eigenschaft hinzu -

@ViewChild(FormGroupDirective) formGroupDirective: FormGroupDirective;

und benutze dies anstelle von this.myForm.reset();

this.formGroupDirective.resetForm();

Dadurch wird die Fehleranzeige zurückgesetzt und auch form.reset () ausgeführt. Aber das Formular zeigt zusammen mit den Feldern immer noch ng-invalidKlasse

Überprüfen Sie diese Antwort auf weitere Details - https://stackoverflow.com/a/56518781/9262627

Abhinav
quelle
0

Ich hatte auch die gleichen Probleme. Mein Problem war, dass ich mat-form-fieldund benutzte formGroup. Nach dem Zurücksetzen wurde das Formularflag submittednicht zurückgesetzt.

Die Lösung, die für mich funktioniert hat, besteht darin, eine Richtlinie zu ngFormverabschieden formGroupund zu verabschieden onSubmit(form). @ViewChild('form') form; In Komponente hinzugefügt und dann verwendet this.form.resetForm();

Prisar
quelle
0

Bei mir hat nichts von oben funktioniert (Angular 7.2, Angular Material 7.3.7).

Versuchen Sie, mit der Submit-Methode ein angezeigtes Ereignis zu übergeben:

<form [formGroup]="group" (ngSubmit)="onSubmit($event)">
    <!-- your form here -->
</form>

Verwenden Sie es dann zum Zurücksetzen currentTargetund anschließend für Ihr Formular:

public onSubmit(event): void {
  // your code here
  event.currentTarget.reset()
  this.group.reset()
}
mpro
quelle
0

Einfache Lösung: Verwenden Sie die Taste mit type="reset"und funktionieren Sie submitForm()zusammen

<form [formGroup]="MyForm" (ngSubmit)="submitForm()">
  <input formControlName="Name">
  <mat-error>  
    <span *ngIf="!tunersForm.get('Name').value && tunersForm.get('Name').touched"></span>  
  </mat-error>
  <button type="reset" [disabled]="!MyForm.valid" (click)="submitForm()">Save</button>
</form>
Andreas Griechihin
quelle
0

Ich hatte kein Glück, die Formularrichtlinie zurückzusetzen. Sie können aber auch den Eingabestatus in "Ausstehend" ändern, um dies zu tun.

this.myForm.get("email").reset();
this.myForm.get("password").reset();
Janith
quelle
0

Für alle, denen dies helfen könnte, verwende ich Angular 9.1.9 und wollte das Formular / die Steuerelemente nicht zurücksetzen, sondern nur die Gesamtgültigkeit des Formulars, also habe ich gerade Folgendes ausgeführt:

this.registerForm.setErrors(null);

... wo registerForm: FormGroupund das die Formularfehler zurücksetzt, was zu Folgendem führt:

this.registerForm.valid

... zurückkehren true.

Das Gleiche gilt für Steuerelemente:

this.registerForm.get('email').setErrors(null)

Sobald das Formular berührt wird, werden diese Fehler ohnehin neu ausgewertet. Wenn dies nicht gut genug ist, benötigen Sie möglicherweise ein boolesches Flag, um genau dann, wenn Sie die Fehler-Benutzeroberfläche ein- / ausblenden möchten, weiter zu bestimmen.

Ich musste die Richtlinie in meinem Fall nicht berühren.

Hingehen
quelle
0
 resetForm() {
    this.myFormGroup.reset();
    this.myFormGroup.controls.food.setErrors(null);
    this.myFormGroup.updateValueAndValidity();
  } 
S. V.
quelle
1
Während dieser Code die Frage möglicherweise beantwortet, würde die Bereitstellung eines zusätzlichen Kontexts darüber, wie und / oder warum das Problem gelöst wird, den langfristigen Wert der Antwort verbessern.
Andreas
0

form.reset() funktioniert nicht mit benutzerdefinierten Formularsteuerelementen wie Angular Material, weshalb die Funktion nicht wie erwartet funktioniert.

Meine Problemumgehung dafür ist ungefähr so

    this.form.reset();
    for (let control in this.form.controls) {
      this.form.controls[control].setErrors(null);
    }

this.form.reset() Das Problem dabei ist, dass Ihre Formcontrol-Werte zurückgesetzt werden, nicht jedoch die Fehler. Sie müssen sie daher einzeln über diese Codezeile zurücksetzen

for (let control in this.form.controls) {
      this.form.controls[control].setErrors(null);
    }

Damit müssen Sie nicht verwenden, FormGroupDirectivewas für mich eine sauberere Lösung ist.

Github-Problem: https://github.com/angular/angular/issues/15741

brijmcq
quelle
-4

Verschieben Sie die Übermittlungsfunktion von Ihrem Formular auf Ihre Schaltfläche und fügen Sie Ihren Schaltflächen Typen hinzu:

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