簡體   English   中英

每個步驟都有單獨組件的角度材質步進器 - ExpressionChangedAfterItHasBeenCheckedError

[英]Angular Material Stepper with Separate Component for each step - ExpressionChangedAfterItHasBeenCheckedError

我有一個材料步進器,步進器的每一步都有形式。 在那里,每個步驟都應由與其關聯的表單控制。

即使已經在 SO 中提出了這個問題,但這些問題的答案並不能解決我的問題。 因此我在問。

父 HTML

<mat-horizontal-stepper linear #stepper>
    <mat-step [stepControl]="frmStepOne">
        <ng-template matStepLabel>Step One Details</ng-template>
        <app-first-step #stepOne></app-first-step>
    </mat-step>
    <mat-step [stepControl]="frmStepTwo">
        <ng-template matStepLabel>Step Two Details</ng-template>
        <app-second-step #stepTwo></app-second-step>
    </mat-step>
</mat-horizontal-stepper> 

在我的父組件中,我有以下內容。

@ViewChild('stepOne') stepOneComponent: FirstStepComponent;
@ViewChild('stepTwo') stepTwoComponent: SecondStepComponent;


get frmStepOne() {
    return this.stepOneComponent ? this.stepOneComponent.frmStepOne : null;
}

get frmStepTwo() {
    return this.stepTwoComponent ? this.stepTwoComponent.frmStepTwo : null;
}

我的孩子類組件

frmStepOne: FormGroup;

constructor(private formBuilder: FormBuilder) {

    this.frmStepOne = this.formBuilder.group({
      name: ['', Validators.required]
    });
}

子類 HTML

<mat-card>

  <form [formGroup]="frmStepOne">

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

    <mat-card-actions>
      <button mat-raised-button matStepperNext class="nav-btn pull-right">Next</button>
    </mat-card-actions>

  </form>

</mat-card>

現在,當我運行應用程序時,在控制台中,我看到以下內容。

ERROR 錯誤:ExpressionChangedAfterItHasBeenCheckedError:檢查后表達式已更改。 以前的值:'stepControl:null'。 當前值:'stepControl:[object Object]'。

正如我之前提到的,在 SO 中有關於相同的討論。 例如,以下鏈接問題的回答和評論建議將表單初始化移動到構造函數中,而不是將它放在 onInit 中。 我已經這樣做了。

每個步驟的角度材料步進組件

但是,我仍然收到錯誤消息。

這是我在 Stackblitz 上的項目 - https://stackblitz.com/github/vigamage/stepper-component-wise

有人可以建議如何擺脫這個問題嗎?

謝謝..

基本上,角度在已經將兩個值的值都設置為null之后檢測到變化。 因此,您需要明確告訴 angular 它應該運行更改檢測。 看看這個演示代碼

我已經刪除了使用get的邏輯,因為直接從 HTML 調用函數是一種不好的做法。 它會被多次調用。 嘗試將控制台日志放入您的代碼中並查看。

我已經使用ngAfterViewInit沿ChangeDetectorRef通知。

export class AppComponent implements AfterViewInit {
  title = 'mat-stepper';

  form1: FormGroup;
  form2: FormGroup;
  @ViewChild('stepOne') stepOneComponent: FirstStepComponent;
  @ViewChild('stepTwo') stepTwoComponent: SecondStepComponent;

  constructor(private cdr :ChangeDetectorRef){}

  ngAfterViewInit(){
    this.form1 = this.stepOneComponent.frmStepOne;
    this.form2 = this.stepTwoComponent.frmStepTwo
    this.cdr.detectChanges();
  }

}

這將解決錯誤

只需將導致此錯誤的變量更改為Observable並使用delay(0) operator pipe傳輸

這是一個工作解決方案的鏈接- 沒有錯誤,也不需要使用變更檢測。

這是一個例子

假設我在html模板中使用了string類型的變量name ,它會導致上述錯誤。

<div>{{ name }}</div> // BOOM ERROR why? 

因為起初name是一些東西,並且在 angular 已經檢查過它之后它被改變了。

所以要解決這個問題..首先將name更改為像name$這樣的Observable

name$: Observable<string>; // name$ replaces name    

private myName$ = new BehaviorSubject<string>();
myNameListener$: Observable<string> = this.myName$.asObservable();
myName(name: string) {
    this.myName$.next(name)
}

現在在ngOnInit()只聽那個 Observable

ngOnInit() {

    this.name$ = this.myNameListener$.pipe(
        delay(0)
    )

}

使用async管道訂閱html模板中的Observable

<div *ngIf=" (name$ | async) as name ">{{ name }}</div> // render your variable

現在將您的實際數據傳遞到您想要的任何地方。

this.myName(data);

這是一個工作解決方案的鏈接- 沒有錯誤,也不需要使用變更檢測。

祝你好運!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM