简体   繁体   中英

How to expand multiple panels properly?

I am working with multiple panels and I added functionality to expandAll/collapseAll panels. My issue is:

Lets say:

1) I expand all panels

2) Now, I collapse ONLY the second panel

3) Now I click on the ExpandAll button (Expecting all panels to be expanded).

Issue: After following the above steps, I can't get the panels to expand.

Here's my code:

PLUNKER

<button (click)="collapseAll()">ExpandAll</button>
<button (click)="expandAll()">CollapseAll</button>

You have two problems with this code:

  1. You have just one property responsible for the collapsed state of every panel. This way it's impossible to control them separately.

  2. You have one-way binding, so when your collapse the panels manually in your view, the model is not updated. I fixed your code and forked the plunker: https://plnkr.co/edit/rfiVj8vEIBDOZ8rIHV5i

The main ideas are:

Have dynamic template to keep your html dry:

<p-panel *ngFor="let panel of panels" 
          [header]="panel.name" 
          [toggleable]="true" 
          [(collapsed)]="panel.isCollapsed" <== notice the "banana-in-a-box" notation [()], which allows two-way binding
          [style]="{'margin-bottom':'20px'}">
    {{ panel.text }}
</p-panel>


export class AppComponent {

  panels = [
    {
      name: 'Panel 1',
      isCollapsed: false,
      text: `The story begins as Don Vito Corleone...`
    },
    {
      name: 'Panel 2',
      isCollapsed: false,
      text: `The story begins as Don Vito Corleone...`
    },
    {
      name: 'Panel 3',
      isCollapsed: false,
      text: `The story begins as Don Vito Corleone...`
    },
    {
      name: 'Panel 4',
      isCollapsed: false,
      text: `The story begins as Don Vito Corleone...`
    },
  ] // you can also move this to a separate file and import

  constructor() {
  }

  expandAll(){
    this.panels.forEach(panel => {
      panel.isCollapsed = false;
    });
  }

  collapseAll(){
    this.panels.forEach(panel => {
      panel.isCollapsed = true;
    });
  }
}

UPDATE If you don't want to extract the text from your panels you don't have to but in that case you won't be able to use *ngFor and you'll have to store the state of each panel in some datastructure of your component.

You can have somthing like this:

panelsCollapsed = [
    {
      isCollapsed: false,
    },
    {
      isCollapsed: false,
    },
    {
      isCollapsed: false,
    },
    {
      isCollapsed: false,
    }, // this can also be just an arry of booleans, I kep it as an object in case you want to add other fields to it

Then in your markup you'd have:

<p-panel header="Panel 1" [toggleable]="true" [collapsed]="panelsCollapsed[0].isCollapsed" [style]="{'margin-bottom':'20px'}">
    The story begins as Don Vito Corleone...
</p-panel>
<p-panel header="Panel 2" [toggleable]="true" [collapsed]="panelsCollapsed[1].isCollapsed" [style]="{'margin-bottom':'20px'}">
    The story begins as Don Vito Corleone...
</p-panel>

The methods for expanding/collapsing all would stay the same.

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