简体   繁体   中英

ExpressionChangedAfterItHasBeenCheckedError: with two sibling Angular components

I'm using Angular Material expansion-panel with Flex-Layout and I would like to split my two expansion-panel into two different components.

I realized a StackBlitz1 HERE using both expansion-panel in the same component. On the other hand, in my second StackBlitz2 HERE , I split these two expansion-panels in two different components, but an error occurs. The error ExpressionChangedAfterItHasBeenCheckedError appears and it comes from my function "changeExpansionPanelState ()" in the HTML file of my two components.

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

If someone has a solution to be able to do the same thing as my StackBlitz1 with two components, I'm interested.

DEMO:

在此处输入图片说明

Thank you in advance!

Chellappan's answer is correct, the reason why is below...

Your HTML uses the panelOpenState boolean component variables to control your view... you instantiate these variables with no value when the component is initialized.

  panelOpenState1: boolean;
  panelOpenState2: boolean;

You then set the value to these component variables after the view is rendered via the service subscription...

 ngAfterViewInit() {
    this.panelState.panelOpenState1$.subscribe(panelOpenState1 => this.panelOpenState1 = panelOpenState1);
    this.panelState.panelOpenState2$.subscribe(panelOpenState2 => this.panelOpenState2 = panelOpenState2);
  }

So when the view is rendered, for [ngClass]="{'flex': panelOpenState2}" the panelOpenState2 component variable is undefined at this point... but then the subscriptions are created which takes the previous checked value of undefined and replaces it with the observable boolean value.

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

The key to avoiding this is to do one of the following...

Instantiate your component variables with a value.

export class FirstPanelComponent implements AfterViewInit {
  panelOpenState1: boolean = true;
  panelOpenState2: boolean = false;

Or create your subscriptions when the component is initialized... before your view is rendered so the component variables are not undefined when the view needs them.

  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);
  }

I finally changed my method and found a simpler solution to my problem without going through service, here is the result:

StackBlitz HERE

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM