Ionic 3 and Angular 4 Multi Level Accordion Menu Example

by - May 04, 2017

This is an example of a multi-level accordion menu with dynamic data using latest Ionic 3 and Angular 4.

1. Create New Ionic 3 and Angular 4 Side Menu App

We will start this tutorial by creating new Ionic 3 and Angular 4 app. This time we will use generated side menu app. Open and edit the terminal or Node.js command line then type this command.
ionic start ionic3-accordion-menu sidemenu --v2
That command will create new Ionic 3 app with the name 'ionic3-accordion-menu' using default template 'sidemenu'. Go to the newly created app folder.
cd ionic3-accordion-menu
Run the Ionic 3 app on the browser.
ionic serve -l
You should see this side menu.
Ionic 3 and Angular 4 Multi Level Accordion Menu Example - Side Menu
Right now, we will skip lazy loading pages configuration because we will focus only on the multilevel accordion menu. You can find more about lazy loading and Ionic 3 getting started here.


2. Create Nested Array of Objects

We have to create nested Array of objects which it's contains multilevel arrays. Create a new folder and JSON file in asset folder.
mkdir src/assets/data
touch src/assets/data/menus.json
Open and edit 'menus.json' then add this lines of data.
[
  {
    "category":"PC",
    "subs": [
      {
        "subcategory":"Processor",
        "manufactures": [
          {
            "manufacture":"Intel"
          },
          {
            "manufacture":"AMD"
          }
        ]
      },
      {
        "subcategory":"Motherboard",
        "manufactures": [
          {
            "manufacture":"Asus"
          },
          {
            "manufacture":"AMD"
          },
          {
            "manufacture":"GigaByte"
          },
          {
            "manufacture":"Intel"
          }
        ]
      },
      {
        "subcategory":"Memory",
        "manufactures": [
          {
            "manufacture":"Visipro"
          },
          {
            "manufacture":"Crucial"
          },
          {
            "manufacture":"VenomRX"
          }
        ]
      }
    ]
  },
  {
    "category":"Laptop",
    "subs": [
      {
        "subcategory":"Notebook",
        "manufactures": [
          {
            "manufacture":"Lenovo"
          },
          {
            "manufacture":"Dell"
          }
        ]
      },
      {
        "subcategory":"Netbook",
        "manufactures": [
          {
            "manufacture":"Lenovo"
          },
          {
            "manufacture":"Dell"
          },
          {
            "manufacture":"Acer"
          },
          {
            "manufacture":"HP"
          }
        ]
      }
    ]
  },
  {
    "category":"Printer",
    "subs": [
      {
        "subcategory":"Laserjet",
        "manufactures": [
          {
            "manufacture":"HP"
          },
          {
            "manufacture":"Brother"
          },
          {
            "manufacture":"Canon"
          },
          {
            "manufacture":"Samsung"
          }
        ]
      },
      {
        "subcategory":"Deskjet",
        "manufactures": [
          {
            "manufacture":"HP"
          },
          {
            "manufacture":"Canon"
          },
          {
            "manufacture":"Epson"
          }
        ]
      }
    ]
  }
]

3. Create and Call Service/Provider for Accessing Data
To access JSON data we have to create new service or provider to keep app modular. Type this command to create it.
ionic g provider DataService
Open and edit 'src/providers/data-service.ts' add 'Response' to 'Http' import.
import { Http, Response } from "@angular/http";
Create this function for call JSON data.
getMenus(){
  return this.http.get('assets/data/menus.json')
   .map((response:Response)=>response.json());
}
Register this service in 'app.module.ts' by open and edit 'src/app/app.module.ts' then add this import.
import { HttpModule } from '@angular/http';
import { DataService } from '../providers/data-service';
Add 'HttpModule' in '@NgModule' imports.
...
imports: [
  BrowserModule,
  IonicModule.forRoot(MyApp),
],
...
Add 'DataService' in '@NgModule' providers.
...
providers: [
  StatusBar,
  SplashScreen,
  {provide: ErrorHandler, useClass: IonicErrorHandler},
  DataService
]
...
Because menu holds by component, we have to edit it to call data for the menu from service/provider. Open and edit 'src/app/app.component.ts' then add this import.
import { DataService } from '../providers/data-service';
Replace this line.
pages: Array<{title: string, component: any}>;
With this.
pages: any;
Now, inject 'DataService' in constructor parameter and add this function for calling JSON data inside of constructor.
constructor(public platform: Platform, public statusBar: StatusBar, public splashScreen: SplashScreen, public dataService: DataService) {
  this.initializeApp();

  this.dataService.getMenus()
    .subscribe((response)=> {
        this.pages = response;
        console.log(this.pages);
    });

}


4. Create Multilevel Accordion Menu

Now, is the point. Creating multilevel Accordion Menu with Ionic 3 and Angular 4. Open and edit 'src/app/app.html' the add this lines of codes inside '<ion-content>'.
<ion-content>
  <ion-list>
    <ion-item *ngFor="let p of pages" text-wrap>
      {{p.category}}
      <ion-list>
        <ion-item *ngFor="let s of p.subs" text-wrap>
          {{s.subcategory}}
          <ion-list>
            <ion-item *ngFor="let m of s.manufactures" text-wrap>
              {{m.manufacture}}
            </ion-item>
          </ion-list>
        </ion-item>
      </ion-list>
    </ion-item>
  </ion-list>
</ion-content>
After we re-run the Ionic 3 app, the menu should look like this.
Ionic 3 and Angular 4 Multi Level Accordion Menu Example - Multi Level Menu
As you can see, there is 3 level of the menu. For that, we have to make accordion to hide child menus. Open and edit 'src/app/app.component.ts' then declare this variable.
showLevel1 = null;
showLevel2 = null;
Create new functions for toggle show/hide level 2 and level 3 of the menu.
toggleLevel1(idx) {
  if (this.isLevel1Shown(idx)) {
    this.showLevel1 = null;
  } else {
    this.showLevel1 = idx;
  }
};

toggleLevel2(idx) {
  if (this.isLevel2Shown(idx)) {
    this.showLevel1 = null;
    this.showLevel2 = null;
  } else {
    this.showLevel1 = idx;
    this.showLevel2 = idx;
  }
};
Also, create the function for check if level 2 and 3 is shown or hidden.
isLevel1Shown(idx) {
  return this.showLevel1 === idx;
};

isLevel2Shown(idx) {
  return this.showLevel2 === idx;
};
Now, open and edit 'src/app/app.html' then replace all list with this list.
<ion-content>
  <ion-list>
    <ion-item *ngFor="let p of pages; let i=index" text-wrap (click)="toggleLevel1('idx'+i)" [ngClass]="{active: isLevel1Shown('idx'+i)}">
      <h4>
        {{p.category}}
        <ion-icon color="success" item-right [name]="isLevel1Shown('idx'+i) ? 'arrow-dropdown' : 'arrow-dropright'"></ion-icon>
      </h4>
      <ion-list *ngIf="isLevel1Shown('idx'+i)">
        <ion-item *ngFor="let s of p.subs; let i2=index" text-wrap (click)="toggleLevel2('idx'+i+'idx'+i2)" [ngClass]="{active: isLevel2Shown('idx'+i+'idx'+i2)}">
          <h4>
            {{s.subcategory}}
            <ion-icon color="success" item-right [name]="isLevel2Shown('idx'+i+'idx'+i2) ? 'arrow-dropdown' : 'arrow-dropright'"></ion-icon>
          </h4>
          <ion-list *ngIf="isLevel2Shown('idx'+i+'idx'+i2)">
            <ion-item *ngFor="let m of s.manufactures" text-wrap>
              {{m.manufacture}}
            </ion-item>
          </ion-list>
        </ion-item>
      </ion-list>
    </ion-item>
  </ion-list>
</ion-content>
Then re-run the Ionic 3 app and see the results in the browser.
Ionic 3 and Angular 4 Multi Level Accordion Menu Example - Multi Level Accordion Menu
That it's for now, we are leaving this tutorial without action for click on each menu item. We know this isn't a best and simple way for creating multiple accordions. For that, we need suggestions and best algorithm to make this tutorial better and useful for everyone.
You can find the source code on our GitHub.
Thanks.

You May Also Like

0 comments