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/


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


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


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

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();

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

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


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();


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()
}

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>

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();

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.


0
 resetForm() {
    this.myFormGroup.reset();
    this.myFormGroup.controls.food.setErrors(null);
    this.myFormGroup.updateValueAndValidity();
  } 

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


-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>
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.