Angular 5 FormGroup重置不会重置验证器


79

我的页面上有一个表单,当我调用FormGroup.reset()它时,将forms类设置为,ng-pristine ng-untouchedFormControl.hasError(...)仍然返回true。我在这里做错了什么?

模板

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

零件

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

柱塞

https://embed.plnkr.co/Hlivn4/


1
您可以尝试拨打电话this.myForm.markAsUntouched();吗?
爆炸药

根据文档,这是行不通的,也没有必要。(v2.angular.io/docs/ts/latest/api/forms/index/...
efarley


这回答了你的问题了吗?如何在提交
ANGULAR

Answers:


148

它(FormGroup)行为正确。您的表单需要用户名和密码,因此,当您重置表单时,该表单应该无效(即,没有用户名/密码的表单无效)。

如果我理解正确,那么这里的问题就是为什么在您第一次加载页面(表单也是无效的)时并没有出现红色错误,而是在您单击按钮时弹出了红色错误。使用Material时,此问题尤其突出。

AFAIK,<mat-error>请检查的有效性FormGroupDirective,而不是FormGroup,并且重置FormGroup不会重置FormGroupDirective。这有点不方便,但是要清除<mat-error>您也需要重置FormGroupDirective

为此,请在模板中定义如下变量:

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

然后在您的组件类中,调用formDirective.resetForm()

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

GitHub问题:https : //github.com/angular/material2/issues/4190


这个问题确实需要解决,就像您说的那样,必须使用此替代方法非常不便。
schankam

2
就我而言,我有一个非常独特的情况,我需要重置“提交的”而不清除表单值(resetForm()对我起作用)。为了解决这个问题,我做了(<any>formDirective).submitted = false;。有点肮脏,但是查看源代码,没有明显的理由要求提交的打字稿定义中的内容为只读。
scourge192 '18

2
阅读github问题,官方回复是“不是我的部门”。la脚,我希望Google员工能更好。
ctilley79 '19

角度为7.2.2:Argument of type NgForm is not assignable to type FormGroupDirective
msanford,

1
经过多种解决方案测试后,该解决方案就可以完美运行!!
JP巴拉·克里希纳

27

阅读评论后,这是正确的方法

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

无需致电 form.clearValidators()


8
这将仅删除验证器,而不重置它们。
Maximillion Bartango

2
要清除验证器this.loginform.clearValidators(),然后将控件的错误设置为null
Jorge Valvert,

可以完美地与Angular 9一起使用。mbue还有其他问题
Petros Kyriakou

22

除了Harry Ninh的解决方案之外,如果您想在组件中访问formDirective而不需要选择一个表单按钮,则:

模板:

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

零件:

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
我认为这是一个更好的答案。标记为答案的变量需要将本地局部变量传递给后面的代码,这是不可取的。但是该答案提供了有关表单如何工作的很好的信息。
山姆

对于Angular 8,`@ ViewChild指令采用两个参数。除了字符串“ formDirective”之外,另一个参数是元数据属性。有关更多信息,请参见angular.io/api/core/ViewChild#description
乔纳森·卡多兹

很好的答案,但他不仅重置了验证程序,而且还重置了表单中的所有值(由用户输入)。
ukie

3

当尝试重置表单组中的特定表单控制器时,以下解决方案为我工作-

 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

我发现在调用resetForm()和reset()之后,提交的未重置并且保持为true,从而导致显示错误消息。这个解决方案对我有用。我在寻找在输入标签上调用select()和focus()的解决方案时发现了它,该标签也不起作用。只需将行包装在setTimeout()中。我认为setTimeout迫使Angular检测更改,但是我可能错了。这有点hack,但是可以解决问题。

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

花了整整一天后找到了这个答案。setTimeout()帮助解决了这一问题。如果您可以添加有关此“ hack”如何工作的描述,将很有帮助。经过测试的角度为7.2.8
Rajendra Thorat

1

添加属性-

@ViewChild(FormGroupDirective) formGroupDirective: FormGroupDirective;

并用它代替 this.myForm.reset();

this.formGroupDirective.resetForm();

这将重置错误显示并完成form.reset()的工作。但是表格和字段仍将显示ng-invalid课程

检查此答案以获取更多详细信息-https://stackoverflow.com/a/56518781/9262627


1

form.reset() 无法在像Angular Material这样的自定义窗体控件上使用,这就是该功能无法按预期工作的原因。

我的解决方法是这样的

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

this.form.reset() 问题是它将重置您的formcontrol值,但不会重置错误,因此您需要通过此代码行分别重置它们

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

有了这个,您不需要使用FormGroupDirective对我来说更干净的解决方案。

Github问题:https : //github.com/angular/angular/issues/15741


0

我也遇到同样的问题。我的问题是我正在使用mat-form-fieldformGroup。重置后,表单submitted标记未重置。

因此,对我有用的解决方案是,将指令和ngForm一起formGroup传递onSubmit(form)@ViewChild('form') form; 在组件中添加 ,然后我用 this.form.resetForm();


0

上面没有什么对我有用(Angular 7.2,Angular Material 7.3.7)。

尝试使用Submit方法传递视图上的事件:

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

然后使用它来重置currentTarget,然后使用您的表单:

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

0

简单修复:将按钮与type="reset"和功能submitForm()一起使用

<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

我没有重置form指令的运气。但是您也可以将输入状态更改为“挂起”。

this.myForm.get("email").reset();
this.myForm.get("password").reset();

0

对于可能对此有所帮助的任何人,我正在运行Angular 9.1.9,并且我不想仅重置表单的整体有效性来重置表单/控件,所以我只运行了:

this.registerForm.setErrors(null);

...在哪里registerForm: FormGroup重置表单错误,导致:

this.registerForm.valid

...返回true

可以对控件执行相同的操作:

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

触摸表单后,无论如何都会重新评估这些错误,因此,如果这还不够好,则当您要开始显示/隐藏错误UI时,可能需要使用布尔值标记来进一步精确定位。

在我的情况下,我不需要触摸指令。


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

1
尽管此代码可以回答问题,但提供有关如何和/或为什么解决问题的其他上下文将提高​​答案的长期价值。
安德里亚斯

-4

将提交功能从表单移到按钮上,然后将类型添加到按钮:

<form [formGroup]="createForm">
  <button (click)="submitForm()" type="submit">Submit</button>
  <button (click)="createForm.reset()" type="reset">Reset</button>
</form>
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.