ExpressionChangedAfterItHasBeenCheckedError:具有两个同级Angular组件

时间:2019-01-02 11:23:25

标签: angular rxjs angular-material panel siblings

我将Angular Material扩展面板与Flex-Layout一起使用,我想将我的两个扩展面板分成两个不同的组件。

我在同一组件中使用两个扩展面板实现了StackBlitz1 HERE。 另一方面,在第二个StackBlitz2 HERE中,我将这两个扩展面板分为两个不同的组件,但是发生了错误。 出现错误ExpressionChangedAfterItHaHasBeenCheckedError,它来自我的两个组件的HTML文件中的函数“ changeExpansionPanelState()”。

<mat-expansion-panel (opened)="changeExpansionPanelState()"
                     (closed)="changeExpansionPanelState()">
  ...
</mat-expansion-panel>

如果有人有一种解决方案能够通过两个组件来完成与StackBlitz1相同的操作,我会很感兴趣。

演示:

enter image description here

提前谢谢!

2 个答案:

答案 0 :(得分:1)

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……但是随后创建的订阅使用了先前检查的值{ {1}}并将其替换为可观察的布尔值。

undefined

  

避免这种情况的关键是执行以下操作之一...

使用值实例化组件变量。

Previous value: 'flex: undefined'. Current value: 'flex: true'

或在初始化组件时创建订阅... 之前,在呈现视图之前,当视图需要它们时,组件变量就不会export class FirstPanelComponent implements AfterViewInit { panelOpenState1: boolean = true; panelOpenState2: boolean = false;

undefined

答案 1 :(得分:0)

我终于改变了方法,找到了一个无需服务即可解决问题的简单方法,结果如下:

StackBlitz HERE