Angular响应式表单:如何在提交后重置表单状态并保留值

60

如何在Angular响应式表单中,只重置表单的状态,并保留修改后的值?

以下是具体步骤:

  • 创建表单并使用服务结果进行setValue
  • 修改表单值并提交表单
  • 若表单已成功提交至服务端,则重置表单状态并保留表单值

如何保留修改后的表单值,并将表单重置至原始状态。

调用form.reset()仅会清空表单。但如果不调用它,表单的状态不会被重置,例如,基于表单状态类(原始 pristine、已编辑 dirty、合法 valid 等)的验证仍将存在。


通常,我会创建一个名为initForm的方法,在ngInit时调用它,并在提交表单后再次调用。 - mareks
8个回答

104

@smnbbrv的解决方案非常有效。

您也可以将实际表单值提供给reset()方法。

假设myReactiveForm是组件中的一个响应式表单。在成功提交表单后(例如调用服务),然后您可以执行以下操作:

this.myReactiveForm.reset(this.myReactiveForm.value);

这将重置表单,并将“新”表单值设置为与您的表单相同的值。

此方法可在Tour of Hero示例中查看 官方Angular.io文档


2
这真是一个巧妙的技巧 :D 不过,我必须承认它应该能够工作 ;) - smnbbrv
是的!通过阅读Angular文档,我们可以找到很棒的解决方案。这些人太......聪明了! - BlackHoleGalaxy
我已经读了四次自从 Angular2 beta 后,现在很累了,所以我会把它留给喜欢的人 :) 我实际上不认为这是一个好的解决方案,因为它不必要地重新编写了所有表单值,并且可能会在大型表单上导致性能问题。 - smnbbrv
11
尝试过此解决方案,但不起作用。由于响应式表单立即接收输入字段的最新值,因此传递给“reset”方法的“this.myReactiveForm.value”不反映表单先前的状态,而是表单上的最新值。因此,这种重置方式将导致无操作。根据此解决方案,表单保持不变,而没有像预期那样还原/重置为先前的状态。 - Yiling

40

这非常简单:

this.form.markAsPristine();
this.form.markAsUntouched();

这将重置表单元数据,使表单再次原始。


1
这个移除了验证部分吗? - sireesha j
@sireeshaj 取决于你的意思。如果你正在使用 Angular Material 控件,请参阅我的答案。 - Simon_Weaver

30

使用@angular/components(material)的用户请注意

如果您正在使用Angular Material控件,并使用mat-error来显示错误,则会增加一个复杂性。这些错误是基于ErrorStateMatcher的结果显示的(除了任何您可能应用的*ngIf)。

默认的ErrorStateMatcher基于布尔值显示错误:

isErrorState(control: FormControl | null, form: FormGroupDirective | NgForm | null): boolean 
{
   return !!(control && control.invalid && (control.touched || (form && form.submitted)));
}

这段话的意思是:

如果表单曾经被提交过,且其中一个控件无效(根据验证规则),那么错误信息将会被显示。

通常情况下这并不是你想要的结果(特别是当你在阅读这个问题时!)。

从源代码来看,除非你在ngForm指令上调用resetForm(而不是FormGroup对象),否则没有办法将submitted设置为false。将状态设置为原始或未触及状态不会将submitted重置为false。

如果您正在使用mat-error,如果出现此问题,您可能会发现创建自己的ErrorStateMatcher(简单接口)以进行自定义逻辑更容易。

注意:ErrorStateMatcher仅适用于angular材料 - 不是标准的angular表单的一部分。


简而言之:从ngForm指令中获取一个模板变量并将其传递给重置方法。然后在其上调用'resetForm'。 - yooloobooy
2
正如这个答案所指出的那样,在这种情况下(当使用 FormGroup#reset() 重置表单时,验证器将在表单上显示错误),请使用模板变量 <form #login="ngForm" ... >,并将登录模板变量传递给您的 (ngSubmit)="submit(login)" 函数,并在其上调用 resetForm()。或者,为了不依赖于提交事件,使用 @ViewChild('login') private _loginNgForm: NgForm;,然后使用 this._loginNgForm.resetForm(); - RcoderNY

14

2020年4月6日: Ionic 5+和Angular 9+

只有一行代码:this.form.reset();

重置FormGroup,将所有后代标记为原始状态并未被触摸,并将所有后代的值设置为null。

 form: FormGroup;

 constructor(private formBuilder: FormBuilder, ) { }

  resetTheForm(): void {
    this.form.reset();
  }

5

我使用补丁值(patch value)来清除响应式表单控件,这种方式适用于我。请尝试以下代码。

onClear() {
   this.formGroup.patchValue({
     fieldName: ''
   });
}

5

对于响应式表单,在使用Angular 7时,我所采用的方法是使用基于模板的表单,并通过表单提交处理程序进行传递,如下所示:

// component.html
 <form #f="ngForm" [formGroup]="form" (ngSubmit)="onSubmit(f)" novalidate>
 ....
</form>


// component.ts

onSubmit(form: NgForm) {

// reset form here
 form.form.markAsPristine();
 form.resetForm();
}


它将重置表单和提交状态为默认值。

2

如果您的表单中有一个禁用的输入框,那么在使用ngForm.resetForm()的参数时,请使用getRawValue()。请参考以下示例:

HTML代码如下:

<form
  (ngSubmit)="formSubmit(myForm)"
  #myForm="ngForm"
>
    ...
</form>

in .TS:

formSubmit(myForm: NgForm) {
   myForm.resetForm(myForm.form.getRawValue());
}

2

有时this.myForm.reset(this.myForm.value);可能无法重置为初始值,因此最好创建一个单独的函数来初始化表单,并在ngOnInit()中调用它,在调用this.myForm.reset(this.myForm.value);之前先调用该函数。

ngOnInit(){
  myFormValues();
}

myFormValues() {
  this.myForm= this.fb.group({
      id: ['', Validators.required],
      name: ['', Validators.required],
    });
}

submitForm() {
  // save data
  myFormValues();
  this.myForm.reset(this.myForm.value)
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接