Accordion tree in Angular TreeView component

27 Aug 202511 minutes to read

An accordion interface allows users to expand and collapse hierarchical content, with the key constraint that only one node can be expanded at any given time. The TreeView component can be customized to implement accordion behavior by utilizing the cssClass property for styling and the nodeSelected event to control expansion logic.

Implementation Overview

The accordion TreeView behavior requires:

  1. Event Handling: Use the nodeSelected event to detect when a user interacts with tree nodes
  2. Programmatic Control: Implement logic to collapse all nodes except the currently selected one
  3. Custom Styling: Apply CSS classes via cssClass property to enhance the accordion appearance
  4. Data Structure: Ensure your hierarchical data supports the expand/collapse operations

The following example demonstrates how to configure a TreeView component with accordion functionality:

import { NgModule } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { FormsModule } from '@angular/forms'
import { TreeViewModule } from '@syncfusion/ej2-angular-navigations'
import { Component, Inject, ViewChild } from '@angular/core';
import { NodeSelectEventArgs } from '@syncfusion/ej2-navigations';
import { TreeViewComponent } from '@syncfusion/ej2-angular-navigations';
/**
 * TreeView Accordion sample
 */
@Component({
    imports: [
        FormsModule, TreeViewModule
    ],
    standalone: true,
    selector: 'app-container',
    template: `<div id='treeparent'><ejs-treeview id='treeElement' #treevalidate [fields]='field'  (nodeSelected)='nodeSelect($event)' [cssClass]='cssClass'></ejs-treeview></div>`
})

export class AppComponent {
    // Data source for TreeView component
    public continents: Object[] = [
        {
            code: "AF", name: "Africa", countries: [
                { code: "NGA", name: "Nigeria" },
                { code: "EGY", name: "Egypt" },
                { code: "ZAF", name: "South Africa" }
            ]
        },
        {
            code: "AS", name: "Asia", countries: [
                { code: "CHN", name: "China" },
                { code: "IND", name: "India", selected: true },
                { code: "JPN", name: "Japan" }
            ]
        },
        {
            code: "EU", name: "Europe", countries: [
                { code: "DNK", name: "Denmark" },
                { code: "FIN", name: "Finland" },
                {
                    code: "AUT", name: "Austria",
                }
            ]
        },
        {
            code: "NA", name: "North America", countries: [
                { code: "USA", name: "United States of America" },
                { code: "CUB", name: "Cuba" },
                { code: "MEX", name: "Mexico" }
            ]
        },
        {
            code: "OC", name: "Oceania", countries: [
                { code: "AUS", name: "Australia" },
                { code: "NZL", name: "New Zealand" },
                { code: "WSM", name: "Samoa" }
            ]
        }
    ];
    public field: Object = { dataSource: this.continents, id: "code", text: "name", child: "countries" };
    public cssClass = "accordiontree";

    @ViewChild('treevalidate') tree?: TreeViewComponent;

    public nodeSelect(args: NodeSelectEventArgs): void {
        if (args.node.classList.contains('e-level-1')) {
            this.tree?.collapseAll();
            this.tree?.expandAll([args.node]);
            (this.tree as TreeViewComponent).expandOn = 'None';
        }
    }
}
@import 'node_modules/@syncfusion/ej2-base/styles/material.css';
@import 'node_modules/@syncfusion/ej2-inputs/styles/material.css';
@import 'node_modules/@syncfusion/ej2-buttons/styles/material.css';
@import 'node_modules/@syncfusion/ej2-angular-base/styles/material.css';
@import 'node_modules/@syncfusion/ej2-angular-navigations/styles/material.css';

#treeparent {
    display: block;
    max-width: 350px;
    max-height: 350px;
    margin: auto;
    overflow: auto;
}
.accordiontree .e-list-item.e-level-1 > .e-fullrow, .accordiontree .e-list-item.e-level-1.e-active > .e-fullrow,  .accordiontree .e-list-item.e-level-1.e-hover > .e-fullrow , .accordiontree .e-list-item.e-level-1 > .e-fullrow, .accordiontree .e-list-item.e-level-1.e-active.e-hover > .e-fullrow {
    background-color: darkslateblue;
    border-color: darkslateblue;
}

.accordiontree .e-list-item.e-level-1 > .e-text-content .e-list-text, .accordiontree .e-list-item.e-level-1.e-active > .e-text-content .e-list-text,  .accordiontree .e-list-item.e-level-1.e-hover > .e-text-content .e-list-text,  .accordiontree .e-list-item.e-level-1.e-active.e-hover > .e-text-content .e-list-text {
    color: white;
    font-size: 16px;
} 
.accordiontree .e-list-item.e-level- .e-icons.e-icon-collapsible, .accordiontree .e-list-item.e-level-1 .e-icons.e-icon-collapsible,.accordiontree .e-list-item.e-level-1 .e-icon-expandable {
    display: none
}

.accordiontree .e-list-item.e-level-2 > .e-fullrow, .accordiontree .e-list-item.e-level-2.e-active > .e-fullrow,  .accordiontree .e-list-item.e-level-2.e-hover > .e-fullrow , .accordiontree .e-list-item.e-level-2 > .e-fullrow, .accordiontree .e-list-item.e-level-2.e-active.e-hover > .e-fullrow {
    background-color: white;
    border-color: white;
}

.accordiontree .e-list-item.e-level-2 > .e-text-content .e-list-text, .accordiontree .e-list-item.e-level-2.e-active > .e-text-content .e-list-text,  .accordiontree .e-list-item.e-level-2.e-hover > .e-text-content .e-list-text,  .accordiontree .e-list-item.e-level-2.e-active.e-hover > .e-text-content .e-list-text {
    color: blue;
    font-size: 14px;
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));