2
votes

I am working on an Angular App using NGRX and the Angular Material Components for the UI.

One component uses mat-accordion to display a list of expansion panels. These expansion panels contain information and ways to manipulate these information.

When information is manipulated, an event is emited to the root component and an action is dispatched to the store, modifying the state. When the store fires these changes through the selectors, the root-component which subscribed to the store, passes the changes to the component containing the mat-accordion and with this the mat-expansion-panels.

The Problem: When changes are emitted all expansionpanels of the mat-accordion close. As the user should be able to make further changes, this is a very big issue concerning user expirience.

Edit 1: I set the expanded input of the expansion-panel to true with <mat-expansion-panel [expaned]="true" ... > and the behaviour changes to allways opening all expansion panels making any changes. Thereby i think the entire component seems to be recreated when the input changes. Maybe this happens because i subscribe at the component above and only pass in the new Data. Will have a look if i can change this by passing observables in the inputs.

Edit 2: I forked ibenjelloun's stackblitz app and added my 2 cents, an example that shows the not working behaviour: https://stackblitz.com/edit/stackoverflow-49691295-qulg9d I found out, that removing the line which mimics the ngrx behaviour it works, but with the breaking line also the example in the root component does not work (sucks, as that should be my: look, i don't try the impossible example). This suprises me a little as the app i am working on does also have an acordion setup the same way, but does work as intended.

Since this is work releated i can't show any of the original code causing the issues.

2
Please provide a stackbltiz examplebugs
Use the <mat-expansion-panel [expanded]="isExpanded"> to keep the state of the expanded panelsibenjelloun
@ibenjelloun i guess with isExpanded you refer to a boolean held in the component.ts? I don't know how to apply this as my expansion panels in the acordion are generated from a list of objects which are displayed in detail in teh extension-panels, so i would need a few isExpanded for every expansion panelSchreiberLex

2 Answers

11
votes

Okay so the answer for this little troublemaker is that i didn't used trackBy in ng-for. trackBy enables angular to keep track of the elements iterated over in the loop, even if a new Object is delivered and thereby manages to keep the expansion panels state.

identifyer = (index:number, item: any) => item.name; and <mat-expansion-panel *ngFor="let c of content; trackBy: identifyer"> seal the deal in the stackblitz example.

https://stackblitz.com/edit/stackoverflow-49691295-qulg9d

1
votes

I suggest you to keep your expanded panel id in a variable, and use it to with the expanded input parameter.

<mat-expansion-panel id="panelA" [expanded]="expandedPanel === 'panelA'">

You can find a running example here.

Edit : You should keep your panels expansion states somewhere, here is a suggestion with an edit of your stackblitz.