直式選單 TreeMenu

1 篇文章 / 0 new
author
直式選單 TreeMenu
bar-menu 用來提供外部使用, node-root, node-sub 則是用來產生巢狀選單的功能
► 使用
<treeMenu></treeMenu>

► tree-menu.c.ts
import { Component, OnInit, Input } from '@angular/core';
 
@Component({
    selector: 'treeMenu',
    templateUrl: './tree-menu.c.html',
    styleUrls: ['./tree-menu.c.scss'],
})
export class TreeMenu {
 
    @Input() items = [
        { title: 'Meun-1', href: '#', children: [
            { title: 'Child-11', href: '#child2', children: null},
            { title: 'Child-12', href: '#', children: [
                { title: 'Sub-1', href: '#sub1', children: null},
                { title: 'Sub-2', href: '#sub2', children: null},
                { title: 'Sub-3', href: '#sub2', children: [
                    { title: 'Sub-31', href: '#sub31', children: null},
                    { title: 'Sub-32', href: '#sub32', children: [
                        { title: 'Sub-32-1', href: '#sub321', children: null},
                        { title: 'Sub-32-2', href: '#sub322', children: null},
                    ]},
                ]}
            ]},
            { title: 'Child-13', href: '#child2', children: null}
        ]},
        { title: 'Meun-2', href: 'page01', children: null},
        { title: 'Meun-3', href: '#', children: [
            { title: 'Child-31', href: '#child3', children: null},
            { title: 'Child-32', href: '#child3', children: null}
        ]}
    ];
}
► tree-menu.c.scss
#sidebar {
  min-width: 180px;
}
.nav-link[data-toggle].collapsed:after {
  content: "▾";
}
.nav-link[data-toggle]:not(.collapsed):after {
  content: "▴";
}
► tree-menu.c.html
<app-node-root [nodes]="items"></app-node-root>
► tree-menu.module.ts
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';/* 子模組引入的是 CommonModule, 非根模組的 BrowserModule*/
import { RouterModule } from '@angular/router';
 
import { TreeMenu } from './tree-menu.c';
import { NodeRoot } from './node-root.c';
import { NodeSub } from './node-sub.c';
 
@NgModule({
    imports: [CommonModule, RouterModule],
    declarations: [TreeMenu, NodeRoot, NodeSub],/* 屬性為 private */
    providers:[],/* service */
    exports: [TreeMenu]/* 讓其屬性為 public 讓外界可讀取*/
})
export class TreeMenuModule { }

► node-root.c.ts
import { Component, Input } from '@angular/core';
import { Router } from '@angular/router';
 
@Component({
    selector: 'app-node-root',
    templateUrl: './node-root.c.html',
    styleUrls: ['./node-root.c.scss']
})
export class NodeRoot {
    @Input() nodes: any;
    constructor(private router: Router) { }
 
    onClick($event) {
        //console.log($event);
        this.router.navigate([$event]);
    }
}
► node-root.c.html
<ul class="nav flex-column flex-nowrap">
    <ng-container *ngFor="let item of nodes">
        <ng-container *ngIf="item.children; else elseTemplate">
            <li class="nav-item">
                <a class="nav-link collapsed" href="#tree-{{ item.title }}" data-toggle="collapse" data-target="#tree-{{ item.title }}">{{ item.title }}</a>
                <div class="collapse" id="tree-{{ item.title }}" aria-expanded="false">
                    <app-node-sub *ngIf="item.children" [nodes]="item.children" [level]="0"></app-node-sub>
                </div>
            </li>
        </ng-container>
        <ng-template #elseTemplate>
            <li class="nav-item">
                <a class="nav-link" routerLink="{{item.href}}">{{ item.title }}</a>
            </li>
        </ng-template>
    </ng-container>
</ul>
► node-root.c.scss
.nav-link[data-toggle].collapsed:after {
    content: "▾";
  }
  .nav-link[data-toggle]:not(.collapsed):after {
    content: "▴";
  }
► node-sub.c.ts
import { Component, Input } from '@angular/core';
import { Router } from '@angular/router';
 
@Component({
    selector: 'app-node-sub',
    templateUrl: './node-sub.c.html',
    styleUrls: ['./node-sub.c.scss']
})
export class NodeSub {
    @Input() nodes: any;
    @Input() level: number;
    constructor(private router: Router) { }
 
    onClick($event) {
        //console.log($event);
        this.router.navigate([$event]);
    }
}
► node-sub.c.html
<ul class="flex-column pl-{{ (level+1)*2 }} nav">
    <ng-container *ngFor="let item of nodes">
        <ng-container *ngIf="item.children; else elseTemplate">
            <li class="nav-item">
                <a class="nav-link collapsed py-1" href="#tree-{{ item.title }}" data-toggle="collapse" data-target="#tree-{{ item.title }}">{{ item.title }}</a>
                <div class="collapse" id="tree-{{ item.title }}" aria-expanded="false">
                    <app-node-sub *ngIf="item.children" [nodes]="item.children" [level]="(level==0) ? level+1 : level"></app-node-sub>
                </div>
            </li>
        </ng-container>
        <ng-template #elseTemplate>
            <li class="nav-item">
                <a class="nav-link py-{{level}}" routerLink="{{item.href}}">{{ item.title }}</a>
            </li>
        </ng-template>
    </ng-container>
</ul>
► node-sub.c.scss
.nav-link[data-toggle].collapsed:after {
    content: "▾";
  }
  .nav-link[data-toggle]:not(.collapsed):after {
    content: "▴";
  }
Free Web Hosting