DEV Community

Rens Jaspers
Rens Jaspers

Posted on

1 1 1 1 1

How To Easily Expand or Collapse All Accordion Items in IonAccordionGroup at Once Without Adding Complexity

The Ionic Accordion Group and the ion-accordion are awesome. Accordions provide collapsible sections in your content to reduce vertical space while organizing and grouping information.

However, I feel there's an important feature that's missing: the ability to easily expand or collapse all accordion items at once.

While it's technically possible to expand or collapse all items at once, the current method is quite cumbersome. You have to use <ion-accordion-group [value]="valuesOfTheAccordionsThatShouldBeExpanded"> and pass an array of all the values of the accordions (or an empty array if you want to collapse all). This approach is problematic for several reasons:

  1. Typically, you don't want to assign a value to each accordion manually. Ionic already handles this automatically, but as a developer, you can't easily see these values.

  2. Your component suddenly has an extra responsibility: managing the state of each accordion group. This adds unnecessary complexity to your app.

Generally, I appreciate that the Ionic team keeps things lean and leaves extra functionalities to the developer. However, in this case, I would have liked to see an accordionGroup.toggleAll / expandAll / collapseAll method.

Fortunately, with Angular directives, it's relatively simple to add this functionality cleanly.

Here's an example:

import { ContentChildren, Directive, QueryList } from "@angular/core";
import { IonAccordion, IonAccordionGroup } from "@ionic/angular/standalone";

@Directive({
  selector: "[appAccordionGroupToggle]",
  exportAs: "appAccordionGroupToggle",
  standalone: true,
})
export class AccordionGroupToggleDirective {
  @ContentChildren(IonAccordion) accordions!: QueryList<IonAccordion>;

  get isCompletelyExpanded() {
    const groupValue = this.host.value;
    return (
      Array.isArray(groupValue) && groupValue?.length === this.accordions.length
    );
  }

  constructor(private host: IonAccordionGroup) {}

  toggle() {
    if (this.isCompletelyExpanded) {
      this.collapse();
    } else {
      this.expand();
    }
  }

  expand() {
    this.host.value = this.accordions.map((accordion) => accordion.value);
  }

  collapse() {
    this.host.value = [];
  }
}
Enter fullscreen mode Exit fullscreen mode

The directive works by using @ContentChildren to get a reference to all ion-accordion items within the accordion group. This allows the directive to access the state (and thus the values) of all the accordions collectively. The constructor injects the host IonAccordionGroup, providing access to the group’s properties and methods.

In the expand method, the directive sets the value of the host accordion group to an array containing the values of all the individual accordions, effectively expanding all of them. In the collapse method, it sets the value to an empty array, collapsing all the accordions.

The toggle method first checks if all accordions are already open by checking the value of isCompletelyExpanded. If it equals true, it collapses them; if not, it expands them.

You can use the directive as follows (don't forget to import the directive in your component):

<ion-content>
  <ion-button (click)="toggler.toggle()">Toggle all</ion-button>
  <ion-button (click)="toggler.expand()">Expand all</ion-button>
  <ion-button (click)="toggler.collapse()">Collapse all</ion-button>
  <ion-accordion-group
    appAccordionGroupToggle
    #toggler="appAccordionGroupToggle"
  >
    <ion-accordion>
      <ion-item slot="header">
        <ion-label>First Accordion</ion-label>
      </ion-item>
      <div slot="content">😎</div>
    </ion-accordion>
    <ion-accordion>
      <ion-item slot="header">
        <ion-label>Second Accordion</ion-label>
      </ion-item>
      <div slot="content">🤩</div>
    </ion-accordion>
    <ion-accordion>
      <ion-item slot="header">
        <ion-label>Third Accordion</ion-label>
      </ion-item>
      <div slot="content">💪</div>
    </ion-accordion>
  </ion-accordion-group>
</ion-content>
Enter fullscreen mode Exit fullscreen mode

In the above example, we use #toggler to create a reference to the instance of the Group toggle. This is possible because we set exportAs: 'appAccordionGroupToggle' in our directive. Now, we can call any of the public methods (toggle, expand, and collapse) directly from our template.

That's it! Now you can use this directive to easily toggle all accordions at once anywhere you like. While I hope the Ionic team will add expand, collapse, and toggle methods to ion-accordion-group in the near future, it's great that Angular components make it so easy to add the desired functionality yourself.

Image of Timescale

🚀 pgai Vectorizer: SQLAlchemy and LiteLLM Make Vector Search Simple

We built pgai Vectorizer to simplify embedding management for AI applications—without needing a separate database or complex infrastructure. Since launch, developers have created over 3,000 vectorizers on Timescale Cloud, with many more self-hosted.

Read full post →

Top comments (0)

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more