ExpressionChangedAfterItHasBeenCheckedError: with two sibling Angular components
ExpressionChangedAfterItHasBeenCheckedError: with two sibling Angular components
我正在使用 Angular Material 带有 Flex-Layout 的扩展面板,我想将我的两个扩展面板分成两个不同的组件。
我实现了 StackBlitz1 HERE 在同一个组件中使用两个扩展面板。
另一方面,在我的第二个 StackBlitz2 HERE 中,我将这两个扩展面板拆分为两个不同的组件,但出现了错误。
出现错误 ExpressionChangedAfterItHasBeenCheckedError,它来自我的两个组件的 HTML 文件中的函数 "changeExpansionPanelState ()"。
<mat-expansion-panel (opened)="changeExpansionPanelState()"
(closed)="changeExpansionPanelState()">
...
</mat-expansion-panel>
如果有人有解决方案可以用两个组件完成与我的 StackBlitz1 相同的事情,我很感兴趣。
演示:
提前致谢!
Chellappan 的回答是正确的,原因如下...
您的 HTML 使用 panelOpenState
布尔组件变量来控制您的视图...您在组件初始化时将这些变量实例化为没有值。
panelOpenState1: boolean;
panelOpenState2: boolean;
您然后将值设置为这些组件变量在呈现视图后 通过服务订阅...
ngAfterViewInit() {
this.panelState.panelOpenState1$.subscribe(panelOpenState1 => this.panelOpenState1 = panelOpenState1);
this.panelState.panelOpenState2$.subscribe(panelOpenState2 => this.panelOpenState2 = panelOpenState2);
}
因此,当呈现视图时,对于 [ngClass]="{'flex': panelOpenState2}"
,此时 panelOpenState2
组件变量为 undefined
...但是随后会创建采用先前检查值的订阅undefined
并将其替换为可观察的布尔值。
Previous value: 'flex: undefined'. Current value: 'flex: true'
The key to avoiding this is to do one of the following...
用一个值实例化您的组件变量。
export class FirstPanelComponent implements AfterViewInit {
panelOpenState1: boolean = true;
panelOpenState2: boolean = false;
或者在初始化组件时创建您的订阅...在您的视图呈现之前,组件变量不会在视图需要它们时undefined
。
ngOnInit(){
this.panelState.panelOpenState1$.subscribe(panelOpenState1 => this.panelOpenState1 = panelOpenState1);
this.panelState.panelOpenState2$.subscribe(panelOpenState2 => this.panelOpenState2 = panelOpenState2);
}
ngAfterViewInit() {
// this.panelState.panelOpenState1$.subscribe(panelOpenState1 => this.panelOpenState1 = panelOpenState1);
// this.panelState.panelOpenState2$.subscribe(panelOpenState2 => this.panelOpenState2 = panelOpenState2);
}
我终于改变了方法,找到了一个更简单的解决方案,无需通过服务,结果如下:
我正在使用 Angular Material 带有 Flex-Layout 的扩展面板,我想将我的两个扩展面板分成两个不同的组件。
我实现了 StackBlitz1 HERE 在同一个组件中使用两个扩展面板。 另一方面,在我的第二个 StackBlitz2 HERE 中,我将这两个扩展面板拆分为两个不同的组件,但出现了错误。 出现错误 ExpressionChangedAfterItHasBeenCheckedError,它来自我的两个组件的 HTML 文件中的函数 "changeExpansionPanelState ()"。
<mat-expansion-panel (opened)="changeExpansionPanelState()"
(closed)="changeExpansionPanelState()">
...
</mat-expansion-panel>
如果有人有解决方案可以用两个组件完成与我的 StackBlitz1 相同的事情,我很感兴趣。
演示:
提前致谢!
Chellappan 的回答是正确的,原因如下...
您的 HTML 使用 panelOpenState
布尔组件变量来控制您的视图...您在组件初始化时将这些变量实例化为没有值。
panelOpenState1: boolean;
panelOpenState2: boolean;
您然后将值设置为这些组件变量在呈现视图后 通过服务订阅...
ngAfterViewInit() {
this.panelState.panelOpenState1$.subscribe(panelOpenState1 => this.panelOpenState1 = panelOpenState1);
this.panelState.panelOpenState2$.subscribe(panelOpenState2 => this.panelOpenState2 = panelOpenState2);
}
因此,当呈现视图时,对于 [ngClass]="{'flex': panelOpenState2}"
,此时 panelOpenState2
组件变量为 undefined
...但是随后会创建采用先前检查值的订阅undefined
并将其替换为可观察的布尔值。
Previous value: 'flex: undefined'. Current value: 'flex: true'
The key to avoiding this is to do one of the following...
用一个值实例化您的组件变量。
export class FirstPanelComponent implements AfterViewInit {
panelOpenState1: boolean = true;
panelOpenState2: boolean = false;
或者在初始化组件时创建您的订阅...在您的视图呈现之前,组件变量不会在视图需要它们时undefined
。
ngOnInit(){
this.panelState.panelOpenState1$.subscribe(panelOpenState1 => this.panelOpenState1 = panelOpenState1);
this.panelState.panelOpenState2$.subscribe(panelOpenState2 => this.panelOpenState2 = panelOpenState2);
}
ngAfterViewInit() {
// this.panelState.panelOpenState1$.subscribe(panelOpenState1 => this.panelOpenState1 = panelOpenState1);
// this.panelState.panelOpenState2$.subscribe(panelOpenState2 => this.panelOpenState2 = panelOpenState2);
}
我终于改变了方法,找到了一个更简单的解决方案,无需通过服务,结果如下: