角7材料步进器反应形式复位不起作用



我在 Angular 7 中使用 Angular 材质。我有许多反应式表单,每个表单都有自己的控制,并且每个表单都更新正在编辑的主要对象的不同属性集合。每个控件都托管在"角度材料步进器"控件的不同步骤中。

每个控件都有一个名为"新增"的按钮,该按钮允许用户将新对象添加到集合,以及一个"编辑"按钮来编辑集合中的任何现有项。每当单击"新增"按钮时,我都会创建一个具有默认值(大多数为空(的新项,并将其绑定到控件中的响应式窗体。

表单始终允许用户单击"添加到集合"按钮(即,该按钮永远不会被禁用(,并且此时会向用户显示验证错误(如果有(。(如果存在验证错误,则不会将该项添加到集合中。

一切正常,直到我转到步进器控件的另一个步骤,然后返回我正在处理的步骤。发生这种情况时,我单击"新增"按钮,即使用户未单击"添加到集合"按钮,我也会立即看到所有必需的验证错误。当我查看控件的值时,我看不出应该显示验证错误的任何原因,但它们是(空输入周围的红色突出显示(。

这是每当用户单击"添加新"时我正在运行的代码:

public resetForm(formGroup: FormGroup) {
if (!formGroup)
return;
formGroup.reset();
formGroup.clearValidators();
// see https://stackoverflow.com/questions/48216330/angular-5-formgroup-reset-doesnt-reset-validators
Object.keys(formGroup.controls).forEach(key => {
if (ignoreControls.indexOf(key) == -1) {
formGroup.get(key).setErrors(null);
formGroup.get(key).markAsPristine();
formGroup.get(key).markAsUntouched();
formGroup.get(key).clearValidators();
formGroup.get(key).updateValueAndValidity();
}
}); 

当我查看单个控件时,在 html 中,我会看到我希望看到的所有内容:

<input _ngcontent-wyd-c14="" class="mat-input-element mat-form-field-autofill-control cdk-text-field-autofill-monitored ng-untouched ng-pristine ng-invalid" formcontrolname="title" matinput="" placeholder="e.g. Customer Service Representative" required="" type="text" ng-reflect-required="" ng-reflect-name="title" ng-reflect-placeholder="e.g. Customer Service Represen" ng-reflect-type="text" id="mat-input-24" aria-invalid="true" aria-required="true">

请注意,该类包含 ng-untouched 和 ng-pristine(以及 ng-invalid(。如果字段是原始且未触及的,则不应显示验证错误。

我怀疑的是,在步进器控件上更改为其他步骤会导致某种表单提交或提交尝试,这就是为什么显示所有错误的原因(form.submit == true或类似的东西(。但是我不知道如何重置任何内容以将表单视为全新的。

谁能帮忙?

(注意:我看到过许多SO文章,建议我需要在form指令上调用resetForm,而不是formGroup(例如,参见Angular 5 FormGroup重置不会重置验证器(。 但是,当我将 #formDirective="ngForm" 添加到我的表单标签并添加到我的打字稿中时:

@ViewChild('formDirective') private formDirective: NgForm;

然后我调用this.formDirective.resetForm((,它没有区别 - 验证错误仍然立即显示。

更新:这是一个堆栈闪电战,基本上显示了问题。从第一步单击"保存并继续",然后在第二步中单击"添加新"。此时将显示表单,没有验证错误。现在单击步进器的"介绍"步骤,然后单击返回"体验"步骤,您将看到返回该步骤时将显示所有验证。这是我实际生产项目中的问题 - 用户应该能够在不触发验证的情况下从一个步骤导航到另一个步骤。在体验组件中,您可以看到每次调用 intiForm 方法时都尝试重置窗体,但您仍然看到错误。为什么?链接: https://stackblitz.com/edit/angular-w4iunu

我怀疑的是更改为步进器上的不同步骤 控制导致某种表单提交或提交尝试,以及 这就是为什么所有错误都显示(form.submit == true或其他东西 像那样(。

你就在这里。单击"添加新"按钮会导致提交表单,因为默认情况下HTML中的任何按钮都具有submit类型。单击Add New按钮后,您的表单将获得submitted标志。

解决方案应该很简单:

<button mat-raised-button color="primary" (click)="addNew()" type="button"...>Add New</button>
^^^^^^^^^
add this

分叉堆叠闪电战

这里的另一个问题是,步进器在计算控制误差状态时会考虑步进interacted属性。一旦你从一个步骤移动到另一个步骤,它就会变得true

您可以通过在selectionChange上重置此属性来解决此问题:

app.component.html

<mat-horizontal-stepper #diaryStepper ... (selectionChange)="stepIndexChanged(diaryStepper)"

app.component.ts

stepIndexChanged(stepper) {
stepper.steps.toArray().forEach(step => step.interacted = false)
}

更新的堆栈闪电战

最新更新