歷程選單主要透過 router 事件內取出 NavigationEnd 的資訊來產生歷程選單, 觀察事件可看見每次點選選單時, router所發出的事件
最後的 NavigationEnd 資料就是我們所要的資訊, 藉此產生選單資料
► breadcrumb.c.ts
reference ng2-breadcrumb, Angular2 Breadcrumb
► breadcrumb.c.ts
import { Component, Input, OnInit, OnChanges } from '@angular/core';
import { Router, NavigationEnd, ActivatedRoute, Params, PRIMARY_OUTLET } from '@angular/router';
interface IBreadcrumb {
label: string;
params?: Params;
url: string;
}
@Component({
selector: 'breadcrumb',
styleUrls: ['./breadcrumb.c.scss'],
templateUrl: './breadcrumb.c.html',
})
export class Breadcrumb {
@Input() useBootstrap: boolean = true;
@Input() prefix: string = '';
public _routerSubscription: any;
public breadcrumbs: IBreadcrumb[];
constructor(private activatedRoute: ActivatedRoute, private router: Router) {
this.breadcrumbs = [];
this._routerSubscription = this.router.events.subscribe((navigationEnd: NavigationEnd) => {
if (navigationEnd instanceof NavigationEnd) {
let root: ActivatedRoute = this.activatedRoute.root;
this.breadcrumbs = this.getBreadcrumbs(root);
}
});
}
ngOnDestroy(): void {
this._routerSubscription.unsubscribe();
}
/* 由 router 事件內取出選單資料 */
private getBreadcrumbs(route: ActivatedRoute, url: string = "", breadcrumbs: IBreadcrumb[] = []): IBreadcrumb[] {
const LABEL: string = "label";
let children: ActivatedRoute[] = route.children;
if (children.length === 0) { return breadcrumbs; }
for (let child of children) {
//verify primary route
if (child.outlet !== PRIMARY_OUTLET) { continue; }
if (!child.snapshot.data.hasOwnProperty(LABEL)) {
return this.getBreadcrumbs(child, url, breadcrumbs);
}
let routeURL: string = child.snapshot.url.map(segment => segment.path).join("/");
//append route URL to URL
url += `/${routeURL}`;
let breadcrumb: IBreadcrumb = {
label: child.snapshot.data[LABEL],
params: child.snapshot.params,
url: url
};
breadcrumbs.push(breadcrumb);
return this.getBreadcrumbs(child, url, breadcrumbs);
}
return breadcrumbs;
}
}
► breadcrumb.c.html
<ul [class.breadcrumb]="useBootstrap">
<li>
<a routerLink="/" [ngClass]="{'breadcrumb-item': useBootstrap}">Home</a>
</li>
<li *ngFor="let breadcrumb of breadcrumbs; let last = last; let first = first" [ngClass]="{'breadcrumb-item': useBootstrap, 'active': last}">
<span *ngIf="first"> /</span>
<a role="button" *ngIf="!last && breadcrumb.url == prefix" [routerLink]="['/']">{{breadcrumb.label}}</a>
<a role="button" *ngIf="!last && breadcrumb.url != prefix" [routerLink]="[breadcrumb.url, breadcrumb.params]">{{breadcrumb.label}}</a>
<span *ngIf="last">{{breadcrumb.label}}</span>
<span *ngIf="last && url == prefix">/</span>
</li>
</ul>
► breadcrumb.module.ts
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';/* 子模組引入的是 CommonModule, 非根模組的 BrowserModule*/
import { RouterModule } from '@angular/router';/* 需注入否則元件內 routerLink 等屬性無法解析 */
import { Breadcrumb } from './breadcrumb.c';
@NgModule({
imports: [CommonModule, RouterModule],
declarations: [Breadcrumb],/* 屬性為 private */
providers:[],/* service */
exports: [Breadcrumb]/* 讓其屬性為 public 讓外界可讀取*/
})
export class BreadcrumbModule { }
► router 需加入 data:{} 資料, 不加入則該 URL 不做歷程顯示
const adminRoutes: Routes = [
{ path: 'admin', component: AdminComponent, data: { label: "admin" }, /* root層的 component 必須定義, 否則 cildren 有設 <router-outlet> 會無法識別 */
children: [
{ path: 'ulist', component: UserListComponent, data: { label: "ulist" } },
{ path: 'u2', component: U2Component, data: { label: "u2" } },
{ path: 'u3', component: U3Component, data: { label: "u3" } },
] },
];
reference ng2-breadcrumb, Angular2 Breadcrumb