Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 4 Multilevel Accordion Issue

I'm trying to make an accordion so when you click a level, it progressively shows you each new level if there is one, but right now it's just recursively displaying all the levels of what will be my accordion. I know there are packages that do this for you, but I want to create my own to get a better understanding of Angular4. This is how my accordion is displaying now, but I want to be able to click into each level.

  • Menu 1
  • Menu 2

    • Sub Menu 2
      • Sub Sub Menu 2
        • Sub Sub Sub Menu 2
  • Menu 3

I'm assuming I need to keep track of the levels with the loop's index or something similar, but I'm not quite sure how.

list.ts

export class List {
  title: string;
  children: any;
}

app.component.ts

import { Component } from '@angular/core';
import { List } from './list';

const LIST: List[] = [
    {
        title: 'Menu 1',
        children: []
    },
    {
        title: 'Menu 2',
        children: [{
            title: 'Sub Menu 2',
            children: [{
                title: 'Sub Sub Menu 2',
                children: [{
                    title: 'Sub Sub Menu 2, Sibling 1',
                    children: []
                },
                {
                    title: 'Sub Sub Sub Menu 2, Sibling 2',
                    children: []
                }]
            }]
        }]

    },
    {
        title: 'Menu 3',
        children: []
    }
];

@Component({
    selector: 'my-app',
    template: `
    <h1>{{title}}</h1>
    <ul>
        <ng-template #recursiveList let-list>
            <li *ngFor="let item of list; let index = index"
            [class.selected]="item === selectedList"
            (click)="onSelect(item)">
                <span> {{item.title}} </span>

                <ul *ngIf="item.children.length > 0">
                    <ng-container *ngTemplateOutlet="recursiveList; context:{ $implicit: item.children }"></ng-container>
                </ul>
            </li>
        </ng-template>
        <ng-container *ngTemplateOutlet="recursiveList; context:{ $implicit: list }"></ng-container>
    </ul>
    `
})
export class AppComponent  {
    title = 'Nested Accordion';
    list = LIST;
    selectedList: List;
    onSelect(list: List): void {
        this.selectedList = list;
    }
}
like image 887
tim Avatar asked Aug 04 '26 03:08

tim


1 Answers

You could add a "hide" property on your List object, which will determine if the list's children are visible or not, and toggle between true/false values, when a list item is clicked.

Here is a demo Plunker based on your code :

https://plnkr.co/edit/CIGAA5BmiKU4hCMsOaIB?p=preview

export class List {
  title: string;
  children: any;
  hide :boolean
}

//our root app component
import {Component, NgModule, VERSION} from '@angular/core'
import {BrowserModule} from '@angular/platform-browser'
import { List } from './list';

const LIST: List[] = [
    {
        title: 'Menu 1',
        hide : true,
        children: [],
    },
    {
        title: 'Menu 2',
        hide : true,
        children: [{
            title: 'Sub Menu 2',
            hide : true,
            children: [{
                title: 'Sub Sub Menu 2',
                hide : true,
                children: [{
                    title: 'Sub Sub Menu 2, Sibling 1',
                    hide : true,
                    children: []
                },
                {
                    title: 'Sub Sub Sub Menu 2, Sibling 2',
                    hide : true,
                    children: []
                }]
            }]
        }]

    },
    {
        title: 'Menu 3',
        hide : true,
        children: []
    }
];

@Component({
  selector: 'my-app',
  template: `
    <h1>{{title}}</h1>
    <ul>
        <ng-template #recursiveList let-list>
            <li *ngFor="let item of list; let index = index">
                <span (click)="onSelect(item)"> {{item.title}} </span>

                <ul *ngIf="item.children.length > 0 && !item.hide">

                    <ng-container *ngTemplateOutlet="recursiveList; context:{ $implicit: item.children }"></ng-container>

                </ul>
            </li>
        </ng-template>
        <ng-container *ngTemplateOutlet="recursiveList; context:{ $implicit: list }"></ng-container>
    </ul>
  `,
})
export class App {
  name:string;
  constructor() {
    this.name = `Angular! v${VERSION.full}`
  }

  title = 'Nested Accordion';
  list = LIST;
  selectedList: List;
  onSelect(list: List): void {
    list.hide = !list.hide;
    this.selectedList = list;
}
like image 186
ktsangop Avatar answered Aug 06 '26 17:08

ktsangop



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!