【问题标题】:Nested Forms in Angular Material Stepper trigger a ExpressionChangedAfterItHasBeenCheckedErrorAngular Material Stepper 中的嵌套表单触发 ExpressionChangedAfterItHasBeenCheckedError
【发布时间】:2019-09-28 15:31:18
【问题描述】:

我正在尝试将 Material Angular mat-step(来自 mat-horizontal-stepper)划分为单独的嵌套子表单组件,并获得关于表单有效性的 ExpressionChangedAfterItHasBeenCheckedError

这个 stackblitz 演示了这个问题: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>

step-one-child-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]));
  }
}

【问题讨论】:

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


    【解决方案1】:

    经过一番挖掘后,我意识到当表单嵌套超过 1 层时会出现更多错误。

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

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

    【讨论】:

      【解决方案2】:

      您需要实施变更检测。

      请使用以下代码更新 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();
        }
      
      
      }
      

      【讨论】:

      • 这确实有效,但看起来更像是一种解决方法,所以我赞成答案,但没有将其标记为已接受,因为我仍然希望有更好的解决方案。
      猜你喜欢
      • 1970-01-01
      • 2020-04-03
      • 1970-01-01
      • 1970-01-01
      • 2021-10-11
      • 1970-01-01
      • 2022-09-28
      • 2018-11-09
      • 1970-01-01
      相关资源
      最近更新 更多