简体   繁体   English

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

[英]angular 7 material stepper reactive form reset not working

I am using Angular Material with Angular 7. I have a number of reactive forms, each in their own control, and each updating different property collections of a primary object being edited. 我将Angular Material与Angular 7一起使用。我有很多反应式,每个反应式都在自己的控件中,每个反应式都更新要编辑的主要对象的不同属性集合。 These controls are each hosted in a different step of the Angular Material Stepper control. 这些控件分别位于Angular Material Stepper控件的不同步骤中。

Each control has a button called "Add New", which allows the user to add a new object to the collection, as well as an "Edit" button to edit any existing item in the collection. 每个控件都有一个名为“添加新”的按钮,该按钮允许用户将新对象添加到集合中,还有一个“编辑”按钮来编辑集合中的任何现有项目。 Whenever the "Add New" button is clicked, I create a new item with default values (most empty), and bind it to the reactive form in the control. 每当单击“添加新”按钮时,我都会创建一个具有默认值的新项目(大多数为空),并将其绑定到控件中的反应形式。

The Form always allows the user to click an "Add to Collection" button (ie, the button is never disabled), and validation errors, if any, are shown to the user at that time. 表单始终允许用户单击“添加到集合”按钮(即,该按钮从不禁用),并且此时会向用户显示验证错误(如果有)。 (The item is not added to the collection if there are validation errors.) (如果存在验证错误,则该项目不会添加到集合中。)

Everything works fine until I go to another step of the Stepper control and then return the the step I'm working on. 一切正常,直到我进入Stepper控件的另一步骤,然后返回正在执行的步骤。 When that happens, and I click the "Add New" button, I see all of the required validation errors immediately, even if the user does not click the "Add to Collection" button. 发生这种情况时,我单击“添加新”按钮,即使用户未单击“添加到收藏集”按钮,我也会立即看到所有必需的验证错误。 When I look at the value of a control, I don't see any reason the validation errors should be showing, but yet they are (red highlight around the empty inputs). 当我查看控件的值时,我看不出验证错误应该显示的任何原因,但是它们却是错误的(在空输入周围以红色突出显示)。

Here is the code I am running whenever a user clicks "Add New": 这是每当用户单击“添加新”时我正在运行的代码:

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

When I look at an individual control, in the html, I see everything I expect to see: 当我查看一个单独的控件时,在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">

Note that the class contains ng-untouched and ng-pristine (as well as ng-invalid). 请注意,该类包含ng-untouched和ng-pristine(以及ng-invalid)。 If a field is pristine and untouched, it should not be showing validation errors. 如果某个字段是原始的且未修改,则该字段不应显示验证错误。

What I suspect is that changing to a different step on the Stepper control causes some kind of form submission or submission attempt, and that is why all the errors show (form.submitted == true or something like that). 我怀疑是在Stepper控件上更改为其他步骤会导致某种形式的表单提交或提交尝试,这就是为什么所有错误都会显示的原因(form.submitted == true或类似的东西)。 But I don't know how to reset anything to treat the form as if it is brand new. 但是我不知道如何重设任何内容以将其视为全新。

Can anyone help? 有人可以帮忙吗?

(Note: I have seen a number of SO articles suggesting that I need to call resetForm on the form directive, as opposed to the formGroup (see, eg, Angular 5 FormGroup reset doesn't reset validators ). But, when I add #formDirective="ngForm" to my form tag, and add to my typescript: (注意:我看过很多SO文章,建议我需要在form指令上调用resetForm,而不是formGroup(例如,参见Angular 5 FormGroup reset不会重置验证器 。)。但是,当我添加# formDirective =“ ngForm”到我的表单标签,并添加到我的打字稿中:

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

and I then call this.formDirective.resetForm(), it makes no difference - the validation errors still display immediately. 然后我将其命名为this.formDirective.resetForm(),这没有区别-验证错误仍会立即显示。

UPDATE: Here is a stackblitz which basically shows the problem. 更新:这是一个基本说明问题的堆栈闪电战。 Click "Save and Continue" from the first step, then click "Add New" in the second step. 从第一步单击“保存并继续”,然后在第二步单击“添加”。 Form appears with no validation errors. 表格显示没有验证错误。 Now click on the "Intro" step of the stepper, and then click back to the "Experiences" step, you will see that all of the validation appears when you return to the step. 现在,单击步进器的“简介”步骤,然后单击回到“体验”步骤,当您返回到该步骤时,您将看到所有验证均出现。 This is the problem in my actual production project - a user should be able to navigate from one step to the other without triggering validation. 这是我实际的生产项目中的问题-用户应该能够在不触发验证的情况下从一个步骤导航到另一步骤。 In the experiences component, you can see am trying to reset the form every time the intiForm method is called, but you still see the errors. 在体验组件中,您可以看到每次调用intiForm方法时都试图重置表单,但是您仍然看到错误。 Why? 为什么? Link: https://stackblitz.com/edit/angular-w4iunu 链接: https//stackblitz.com/edit/angular-w4iunu

What I suspect is that changing to a different step on the Stepper control causes some kind of form submission or submission attempt, and that is why all the errors show (form.submitted == true or something like that). 我怀疑是在Stepper控件上更改为其他步骤会导致某种形式的表单提交或提交尝试,这就是为什么所有错误都会显示的原因(form.submitted == true或类似的东西)。

You're right here. 你在这里 Click on "Add New" button causes form to be submitted because any button in HTML by default has type submit . 单击“添加新”按钮将导致提交表单,因为默认情况下,HTML中的任何按钮的类型submit Once you click on Add New button your form gets submitted flag. 单击Add New按钮后,您的表单将被submitted标志。

The solution should be simple: 解决方案应该很简单:

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

Forked Stackblitz 分叉的Stackblitz

Another issue here is that Stepper takes into account interacted property of step when calculating error status for control. 这里的另一个问题是,步进器在计算控制的错误状态时会考虑步骤的interacted属性。 Once you move from one step to another it becomes true . 一旦从一个步骤转到另一个步骤,它就会变为true

You can workaround this behavior by resetting this property on selectionChange : 您可以通过在selectionChange上重置此属性来解决此问题:

app.component.html app.component.html

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

app.component.ts app.component.ts

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

Updated Stackblitz 更新了Stackblitz

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM