- สร้างโปรเจ็กส์ใหม่
- สร้างไฟล์ menus.json
- Create and Call Service/Provider for Accessing Data
- Create Multilevel Accordion Menu
1. สร้างโปรเจ็กส์ใหม่
[code]
ionic start mySidemenu sidemenu
[/code]
2. สร้างไฟล์ menus.json
สร้างโฟลเดอร์ data และไฟล์ menus.json
[code]
mkdir src/assets/data
touch src/assets/data/menus.json
[/code]
src/assets/data/menus.json
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 |
[ { "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
[code]
ionic g provider DataService
[/code]
src/providers/data-service/data-service.ts
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
import { HttpClient } from '@angular/common/http'; import { Injectable } from '@angular/core'; import { Response } from "@angular/http"; import 'rxjs/add/operator/map' @Injectable() export class DataServiceProvider { constructor(public http: HttpClient) { console.log('Hello DataServiceProvider Provider'); } getMenus() { return this.http.get('assets/data/menus.json').map((response: Response) => response); } } |
src/app/app.module.ts
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
import { BrowserModule } from '@angular/platform-browser'; import { ErrorHandler, NgModule } from '@angular/core'; import { IonicApp, IonicErrorHandler, IonicModule } from 'ionic-angular'; import { MyApp } from './app.component'; import { HomePage } from '../pages/home/home'; import { ListPage } from '../pages/list/list'; import { StatusBar } from '@ionic-native/status-bar'; import { SplashScreen } from '@ionic-native/splash-screen'; import { DataServiceProvider } from '../providers/data-service/data-service'; import { HttpClientModule } from '@angular/common/http'; @NgModule({ declarations: [ MyApp, HomePage, ListPage ], imports: [ BrowserModule, IonicModule.forRoot(MyApp), HttpClientModule ], bootstrap: [IonicApp], entryComponents: [ MyApp, HomePage, ListPage ], providers: [ StatusBar, SplashScreen, {provide: ErrorHandler, useClass: IonicErrorHandler}, DataServiceProvider ] }) export class AppModule {} |
src/app/app.component.ts
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
import { Component, ViewChild } from '@angular/core'; import { Nav, Platform } from 'ionic-angular'; import { StatusBar } from '@ionic-native/status-bar'; import { SplashScreen } from '@ionic-native/splash-screen'; import { HomePage } from '../pages/home/home'; //import { ListPage } from '../pages/list/list'; import { DataServiceProvider } from '../providers/data-service/data-service'; @Component({ templateUrl: 'app.html' }) export class MyApp { @ViewChild(Nav) nav: Nav; rootPage: any = HomePage; //pages: Array<{title: string, component: any}>; pages: any; // constructor(public platform: Platform, public statusBar: StatusBar, public splashScreen: SplashScreen) { // this.initializeApp(); // // used for an example of ngFor and navigation // this.pages = [ // { title: 'Home', component: HomePage }, // { title: 'List', component: ListPage } // ]; // } constructor(public platform: Platform, public statusBar: StatusBar, public splashScreen: SplashScreen, public dataService: DataServiceProvider) { this.initializeApp(); this.dataService.getMenus() .subscribe((response) => { this.pages = response; console.log(this.pages); }); } initializeApp() { this.platform.ready().then(() => { // Okay, so the platform is ready and our plugins are available. // Here you can do any higher level native things you might need. this.statusBar.styleDefault(); this.splashScreen.hide(); }); } openPage(page) { // Reset the content nav to have just this page // we wouldn't want the back button to show in this scenario this.nav.setRoot(page.component); } } |
4. Create Multilevel Accordion Menu
src/app/app.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
<ion-menu [content]="content"> <ion-header> <ion-toolbar> <ion-title>Menu</ion-title> </ion-toolbar> </ion-header> <ion-content> <!-- <ion-list> <button menuClose ion-item *ngFor="let p of pages" (click)="openPage(p)"> {{p.title}} </button> </ion-list> --> <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> </ion-content> </ion-menu> <!-- Disable swipe-to-go-back because it's poor UX to combine STGB with side menus --> <ion-nav [root]="rootPage" #content swipeBackEnabled="false"></ion-nav> |
ลองรันดูจะเห็นเมนูขึ้นแบบภาพนี้ละ แต่ยังกดอะไรไม่ได้
ทำให้เมนูมันอินเทอร์แอคทีพ
src/app/app.component.ts
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
import { Component, ViewChild } from '@angular/core'; import { Nav, Platform } from 'ionic-angular'; import { StatusBar } from '@ionic-native/status-bar'; import { SplashScreen } from '@ionic-native/splash-screen'; import { HomePage } from '../pages/home/home'; import { DataServiceProvider } from '../providers/data-service/data-service'; @Component({ templateUrl: 'app.html' }) export class MyApp { @ViewChild(Nav) nav: Nav; rootPage: any = HomePage; pages: any; showLevel1 = null; showLevel2 = null; constructor(public platform: Platform, public statusBar: StatusBar, public splashScreen: SplashScreen, public dataService: DataServiceProvider) { this.initializeApp(); this.dataService.getMenus() .subscribe((response) => { this.pages = response; console.log(this.pages); }); } initializeApp() { this.platform.ready().then(() => { // Okay, so the platform is ready and our plugins are available. // Here you can do any higher level native things you might need. this.statusBar.styleDefault(); this.splashScreen.hide(); }); } openPage(page) { // Reset the content nav to have just this page // we wouldn't want the back button to show in this scenario this.nav.setRoot(page.component); } 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; } }; isLevel1Shown(idx) { return this.showLevel1 === idx; }; isLevel2Shown(idx) { return this.showLevel2 === idx; }; } |
src/app/app.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
<ion-menu [content]="content"> <ion-header> <ion-toolbar> <ion-title>Menu</ion-title> </ion-toolbar> </ion-header> <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> </ion-menu> <!-- Disable swipe-to-go-back because it's poor UX to combine STGB with side menus --> <ion-nav [root]="rootPage" #content swipeBackEnabled="false"></ion-nav> |
เมื่อกดที่เมนูหลัก ก็จะแสดงเมนูย่อย
แต่เมื่อกดเมนูยังไม่ได้ทำ link ไปไหน
ยังมีปัญหาคือ ถ้าเมนูหลักไม่มีเมนูย่อย ก็ยังแสดง ลูกศรอยู่ คงต้องใช้ *ngIf
มาช่วยซ่อนเมนู
Link