Angular Material Stepper中的嵌套表单会触发ExpressionChangedAfterItHaHasBeenCheckedError

时间:2019-05-10 17:37:52

标签: angular angular-material angular-material2 angular-forms

我正在尝试将材质角mat-step(来自mat-horizontal-stepper)划分为单独的嵌套子表单组件,并获得一个ExpressionChangedAfterItHasBeenCheckedError关于表单有效性的信息。 / p>

此堆叠闪电演示了此问题:https://stackblitz.com/edit/mat-stepper-components

嵌套的组件在第一步中。

有趣的是,如第二步所示,如果只有一层嵌套(如果步骤没有嵌套的子表单),则不会发生此问题。

这是代码的主要部分:

create-profile.component.html

<mat-horizontal-stepper [linear]=true #stepper>
    <mat-step [stepControl]="frmStepOne">
        <ng-template matStepLabel>Step One Details</ng-template>
        <form [formGroup]="frmStepOne"><ng-template matStepLabel>Step One</ng-template>
            <step-one-component></step-one-component>
        </form>
  </mat-step>
    <mat-step [stepControl]="frmStepTwo">
        <ng-template matStepLabel>Step Two Details</ng-template>
        <form [formGroup]="frmStepTwo">
            <step-two-component></step-two-component>
        </form>
    </mat-step>
</mat-horizontal-stepper>

create-profile.component.ts

  //...
  constructor(private fb: FormBuilder) {
    this.frmStepOne = new FormGroup({});
    this.frmStepTwo = new FormGroup({});
  }

step-one.component.html

<step-one-child-one></step-one-child-one>

step-one.component.ts

// nothing interesting, just component boilerplate

step-one-child-one.component.html

<mat-form-field>
  <input matInput formControlName="name" placeholder="Name" required>
</mat-form-field>

第一个孩子一个one.component.ts

@Component({
  selector: 'step-one-child-one',
  templateUrl: './step-one-child-one.component.html',
  viewProviders: [
    {
      provide: ControlContainer,
      useExisting: FormGroupDirective
    }
  ]
})
export class StepOneChildOneComponent {
  constructor(private parent: FormGroupDirective) {
  }

  ngOnInit() {
    this.parent.form.addControl('name', new FormControl('', [Validators.required]));
  }
}

2 个答案:

答案 0 :(得分:1)

您需要实施变更检测。

请使用以下代码更新create-profile.component.ts

import { Component, ViewChild, Input, ChangeDetectorRef, AfterViewChecked } from '@angular/core';
import { FormGroup, FormControl, Validators, FormBuilder } from '@angular/forms';
import { MatStepper } from '@angular/material';
import { StepOneComponent } from './step-one.component';
import { StepTwoComponent } from './step-two.component';
import { StepThreeComponent } from './step-three.component';

@Component({
  selector: 'create-profile-component',
  templateUrl: './create-profile.component.html'
})

export class CreateProfileComponent implements AfterViewChecked {

  frmStepOne: FormGroup;
  frmStepTwo: FormGroup;
  @ViewChild('StepTwoComponent') stepThreeComponent: StepThreeComponent;

  get frmStepThree() {
    return this.stepThreeComponent ? this.stepThreeComponent.frmStepThree : null;
  }

  constructor(private fb: FormBuilder,
  private changeDetect: ChangeDetectorRef) {
    this.frmStepOne = new FormGroup({});
    this.frmStepTwo = new FormGroup({});
  }

  ngAfterViewChecked(): void {
    this.changeDetect.detectChanges();
  }


}

答案 1 :(得分:0)

经过一番挖掘,我发现当表格嵌套的深度超过1层时,还会有更多的错误。

我最终将表单有效性从step-one转发到create-profile,并使用它来在completed上设置mat-step属性。

然后我只有一层嵌套,并且一切正常:)