Accordion component on github

Displays collapsible content panels for presenting information in a limited amount of space

The accordion component builds on top of the collapse directive to provide a list of items, with collapsible bodies that are collapsed or expanded by clicking on the item's header.

The easiest way to add an accordion component to your app (will be added to the root module)

Basic

#

Click headers to expand/collapse content that is broken into logical sections, much like tabs.

<accordion>
  <accordion-group heading="Static Header">
    This content is straight in the template.
  </accordion-group>
  <accordion-group heading="Another group">
    <p>Some content</p>
  </accordion-group>
  <accordion-group heading="Another group">
    <p>Some content</p>
  </accordion-group>
  <accordion-group heading="Another group">
    <p>Some content</p>
  </accordion-group>
</accordion>
import { Component } from '@angular/core';

@Component({
  // eslint-disable-next-line @angular-eslint/component-selector
  selector: 'demo-accordion-basic',
  templateUrl: './basic.html',
  standalone: false
})
export class DemoAccordionBasicComponent {}

With animation

#

Use input property or config property isAnimated to enable/disable animation

<accordion [isAnimated]="true">
  <accordion-group heading="Static Header">
    This content is straight in the template.
  </accordion-group>
  <accordion-group heading="Another group">
    <p>Some content</p>
  </accordion-group>
  <accordion-group heading="Another group">
    <p>Some content</p>
  </accordion-group>
  <accordion-group heading="Another group">
    <p>Some content</p>
  </accordion-group>
</accordion>
import { Component } from '@angular/core';

@Component({
  // eslint-disable-next-line @angular-eslint/component-selector
  selector: 'demo-accordion-animation',
  templateUrl: './animated.html',
  standalone: false
})
export class DemoAccordionAnimatedComponent {}

Group opening event

#

Accordion with isOpenChange event listener.

<accordion>
  <accordion-group heading="Group without isOpenChange event listener">
    <p>Some content</p>
  </accordion-group>
  <accordion-group heading="Group with isOpenChange event listener" (isOpenChange)="log($event)">
    <p>Some content</p>
  </accordion-group>
  <accordion-group heading="Group with isOpenChange event listener" (isOpenChange)="log($event)">
    <p>Some content</p>
  </accordion-group>
</accordion>
import { Component } from '@angular/core';

@Component({
  // eslint-disable-next-line @angular-eslint/component-selector
  selector: 'demo-accordion-open-event',
  templateUrl: './open-event.html',
  standalone: false
})
export class DemoAccordionOpenEventComponent {
  log(event: boolean) {
    console.log(`Accordion has been ${event ? 'opened' : 'closed'}`);
  }
}

Custom HTML

#

<accordion>
  <accordion-group>
    <button
      class="btn btn-link btn-block justify-content-between d-flex w-100  shadow-none"
      accordion-heading type="button">
      <div class="pull-left float-left">I can have markup!</div>
      <span class="badge badge-secondary bg-secondary float-right pull-right">Some HTML here</span>
    </button>
    This is just some content to illustrate fancy headings.
  </accordion-group>
  <accordion-group>
    <button class="btn btn-link shadow-none" accordion-heading type="button">
      I can have markup, too!
    </button>
    <span class="badge badge-secondary bg-secondary center">And some HTML here</span>
  </accordion-group>
</accordion>
import { Component } from '@angular/core';
import { getBsVer, IBsVersion } from 'ngx-bootstrap/utils';

@Component({
  // eslint-disable-next-line @angular-eslint/component-selector
  selector: 'demo-accordion-custom-html',
  templateUrl: './custom-html.html',
  standalone: false
})
export class DemoAccordionCustomHTMLComponent {
  get _getBsVer(): IBsVersion {
    return getBsVer();
  }
}

Disabled

#

<p>
  <button type="button" class="btn btn-primary btn-sm" (click)="isFirstDisabled = !isFirstDisabled">
    Enable / Disable first panel
  </button>
</p>

<accordion>
  <accordion-group heading="Static Header"
                   [isDisabled]="isFirstDisabled">
    This content is straight in the template.
  </accordion-group>
  <accordion-group heading="Content 1">
    <p>accordion 1</p>
  </accordion-group>
  <accordion-group heading="Content 2">
    <p>accordion 2</p>
  </accordion-group>
</accordion>
import { Component } from '@angular/core';

@Component({
  // eslint-disable-next-line @angular-eslint/component-selector
  selector: 'demo-accordion-disabled',
  templateUrl: './disabled.html',
  standalone: false
})
export class DemoAccordionDisabledComponent {
  isFirstDisabled = false;
}

Initially opened

#

This content is straight in the template.
<accordion>
  <accordion-group heading="Content 1">
    <p>accordion 1</p>
  </accordion-group>
  <accordion-group heading="Initially expanded"
                   [isOpen]="isFirstOpen">
    This content is straight in the template.
  </accordion-group>
  <accordion-group heading="Content 2">
    <p>accordion 3</p>
  </accordion-group>
</accordion>
import { Component } from '@angular/core';

@Component({
  // eslint-disable-next-line @angular-eslint/component-selector
  selector: 'demo-accordion-opened',
  templateUrl: './opened.html',
  standalone: false
})
export class DemoAccordionOpenedComponent {
  isFirstOpen = true;
}

Dynamic accordion

#

<p>
  <button type="button" class="btn btn-primary btn-sm" (click)="addGroupItem()">
    Add Group Item
  </button>
</p>

<accordion>
  @for (group of groups; track group) {
    <accordion-group [heading]="group.title">
      {{ group?.content }}
    </accordion-group>
  }
</accordion>
import { Component } from '@angular/core';

@Component({
  // eslint-disable-next-line @angular-eslint/component-selector
  selector: 'demo-accordion-dynamic',
  templateUrl: './dynamic.html',
  standalone: false
})
export class DemoAccordionDynamicComponent {
  groups = [
    {
      title: 'Dynamic Group Header - 1',
      content: 'Dynamic Group Body - 1'
    },
    {
      title: 'Dynamic Group Header - 2',
      content: 'Dynamic Group Body - 2'
    }
  ];

  addGroupItem(): void {
    this.groups.push({
      title: `Dynamic Group Header - ${this.groups.length + 1}`,
      content: `Dynamic Group Body - ${this.groups.length + 1}`
    });
  }
}

Dynamic body content

#

<accordion>
  <accordion-group heading="Dynamic Body Content">
    <p>The body of the accordion group grows to fit the contents</p>
    <button type="button" class="btn btn-primary btn-sm" (click)="addItem()">Add
      Item
    </button>
    <button type="button" class="btn btn-primary btn-sm ms-3 ml-3" (click)="removeItem()">Remove
      Item
    </button>
    @for (item of items; track item) {
      <div>{{item}}</div>
    }
  </accordion-group>
  <accordion-group heading="Content 2">
    <p>accordion 2</p>
  </accordion-group>
  <accordion-group heading="Content 3">
    <p>accordion 3</p>
  </accordion-group>
</accordion>
import { Component } from '@angular/core';

@Component({
  // eslint-disable-next-line @angular-eslint/component-selector
  selector: 'demo-accordion-dynamic-body',
  templateUrl: './dynamic-body.html',
  standalone: false
})
export class DemoAccordionDynamicBodyComponent {
  items = ['Item 1', 'Item 2', 'Item 3'];

  addItem(): void {
    this.items.push(`Item ${this.items.length + 1}`);
  }

  removeItem(): void {
    this.items = this.items.slice(0, this.items.length - 1);
  }
}

Manual toggle

#

accordion 3

<p>
  <button type="button" class="btn btn-primary btn-sm"
          (click)="isOpen = !isOpen">Toggle last panel
  </button>
</p>

<accordion>
  <accordion-group heading="Content 1">
    <p>accordion 1</p>
  </accordion-group>
  <accordion-group heading="Content 2">
    <p>accordion 2</p>
  </accordion-group>
  <accordion-group [isOpen]="isOpen" heading="Last panel">
    <p>accordion 3</p>
  </accordion-group>
</accordion>
import { Component } from '@angular/core';

@Component({
  // eslint-disable-next-line @angular-eslint/component-selector
  selector: 'demo-accordion-manual-toggle',
  templateUrl: './manual-toggle.html',
  standalone: false
})
export class DemoAccordionManualToggleComponent {
  isOpen = true;
}

Open only one at a time

#

<div class="checkbox">
  <label>
    <input type="checkbox" [(ngModel)]="oneAtATime">
    Open only one at a time
  </label>
</div>

<accordion [closeOthers]="oneAtATime">
  <accordion-group heading="Header">
    This content is straight in the template.
  </accordion-group>
  <accordion-group heading="Content 1">
    <p>Content 1</p>
  </accordion-group>
  <accordion-group heading="Content 2">
    <p>Content 2</p>
  </accordion-group>
</accordion>
import { Component } from '@angular/core';

@Component({
  // eslint-disable-next-line @angular-eslint/component-selector
  selector: 'demo-accordion-one-time',
  templateUrl: './one-at-a-time.html',
  standalone: false
})
export class DemoAccordionOneAtATimeComponent {
  oneAtATime = true;
}

Styling

#

This content is straight in the template.
<accordion>
  <accordion-group heading="Static Header, initially expanded"
                   [panelClass]="customClass"
                   [isOpen]="isFirstOpen">
    This content is straight in the template.
  </accordion-group>
  <accordion-group heading="Content 1">
    <p>accordion 1</p>
  </accordion-group>
  <accordion-group heading="Content 2" panelClass="customClass">
    <p>accordion 2</p>
  </accordion-group>
</accordion>
import { Component } from '@angular/core';

@Component({
  // eslint-disable-next-line @angular-eslint/component-selector
  selector: 'demo-accordion-styling',
  templateUrl: './styling.html',
  standalone: false
})
export class DemoAccordionStylingComponent {
  customClass = 'customClass';
  isFirstOpen = true;
}

Configuring defaults

#

<accordion [isAnimated]="true">
  <accordion-group heading="Header">
    This content is straight in the template.
  </accordion-group>
  <accordion-group heading="Content 1">
    <p>Content 1</p>
  </accordion-group>
  <accordion-group heading="Content 2">
    <p>Content 2</p>
  </accordion-group>
</accordion>
import { Component } from '@angular/core';
import { AccordionConfig } from 'ngx-bootstrap/accordion';

// such override allows to keep some initial values

export function getAccordionConfig(): AccordionConfig {
  return Object.assign(new AccordionConfig(), { closeOthers: true });
}

@Component({
  // eslint-disable-next-line @angular-eslint/component-selector
  selector: 'demo-accordion-config',
  templateUrl: './config.html',
  providers: [{ provide: AccordionConfig, useFactory: getAccordionConfig }],
  standalone: false
})
export class DemoAccordionConfigComponent {}

API Reference

ng add ngx-bootstrap  --component accordion
### Standalone component usage
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';

import { AccordionComponent, AccordionPanelComponent } from 'ngx-bootstrap/accordion';

@Component({
  standalone: true,
  imports: [
    BrowserAnimationsModule,
    AccordionComponent,
    AccordionPanelComponent
    ...
  ]
})
export class AppComponent(){}

Also should be added web-animations-js polyfill for IE browser (Edge)
### Module usage
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';

import { AccordionModule } from 'ngx-bootstrap/accordion';

@NgModule({
  imports: [
    BrowserAnimationsModule,
    AccordionModule,
    ...
  ]
})
export class AppModule(){}

Also should be added web-animations-js polyfill for IE browser (Edge)

AccordionComponent

Displays collapsible content panels for presenting information in a limited amount of space.

Selector

AccordionPanelComponent

Accordion heading

Instead of using heading attribute on the accordion-group, you can use an accordion-heading attribute on any element inside of a group that will be used as group's header template.

Selector

AccordionConfig

Configuration service, provides default values for the AccordionComponent.

Properties

closeOthers
Type: boolean
Default value: false

Whether the other panels should be closed when a panel is opened

isAnimated
Type: boolean
Default value: false

turn on/off animation

Basic

With animation

Group opening event

Custom HTML

Disabled

Initially opened

This content is straight in the template.

Dynamic accordion

Dynamic body content

Manual toggle

accordion 3

Open only one at a time

Styling

This content is straight in the template.

Configuring defaults