0
votes

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:

enter image description here

Thank you in advance!

2

2 Answers

1
votes

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

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

StackBlitz HERE