[英]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.