Simple expanding list independent open & close

I have built code for a simple expanding list

When i click on each list they open one at a time - when one opens the other one closes.

How do I get them to open and close independently?

home.html

<ion-card>
 <ion-list>
   <button (click)="toggleGroup(1)" ion-item text-wrap>
      <ion-icon color="success" item-left [name]="isGroupShown(1) ? 'remove-circle' : 'add-circle'" align-items-start></ion-icon>
        <ion-label><strong>Item 1</strong></ion-label>
      </button>
  </ion-list>
  <ion-list>
      <div *ngIf="isGroupShown(1)" padding>
        Item 1 content goes here
      </div>
  </ion-list>
</ion-card>

<ion-card>
  <ion-list>
    <button (click)="toggleGroup(2)" ion-item text-wrap>
      <ion-icon color="success" item-left [name]="isGroupShown(2) ? 'remove-circle' : 'add-circle'" align-items-start></ion-icon>
        <ion-label><strong>Item 2</strong></ion-label>
      </button>
  </ion-list>
  <ion-list>
      <div *ngIf="isGroupShown(2)" padding>
        Item 2 content goes here
      </div>
  </ion-list>
</ion-card>

home.ts

export class HomePage {

  shownGroup = null;

  constructor(
    public navCtrl: NavController, 
    public navParams: NavParams) {
  }

    // Methods for expanding list
    toggleGroup(group) {
      if (this.isGroupShown(group)) {
          this.shownGroup = null;
      } else {
          this.shownGroup = group;
      }
    };
    
    isGroupShown(group) {
      return this.shownGroup === group;
    };
  
}

You are using 1 variable to determine which group should be shown. If you want them to operate independently then you should track them independently either by using 1 variable for each group or if you don’t know the number of groups at compile time you could just use an array of booleans. Something like this.

export class HomePage {

  groupsVisible: boolean[] = [ true, true ];

  constructor(
    public navCtrl: NavController, 
    public navParams: NavParams) {
  }

    // Methods for expanding list
    toggleGroup(group: number) : void {
      if (group < 0 || group >= this.groupsVisible.length) {
          console.log(`Error: group index out of bounds, ${group}`);
          return;
      }
      this.groupsVisible[ group ] = !this.groupsVisible[ group ];
    };
    
    isGroupShown(group): boolean {
      if (group < 0 || group >= this.groupsVisible.length) {
          console.log(`Error: group index out of bounds, ${group}`);
          return;
      }
      return this.groupsVisible[ group ];
    };
  
}

Depending on whether or not you’ll want to use this other places you may want to consider just making the expanding group it’s own component and then just having it as a list.

2 Likes

This is perfect, thanks so much

Usually you don’t unroll loops like this. More typically you are using ngFor to loop across an array of backing objects, and in that case I find it generally more readable and straightforward to fold the boolean indicating whether or not the group is open into that array, instead of having a parallel one.

Another benefit of this approach is that you never have to be passing indexes, and therefore have no need for bounds checking and can reduce the ngIf predicate to a simple property access.

1 Like

Thanks, I would be interested if you could show an example of what you mean.