完成了實作的小程式後
今天來講一下如何設計好一個後台畫面
需要用到Angular Material的Toolbar
與Sidenav
通常我們需要先建一個component
畫面上在擺入mat-toolbar
與mat-sidenav
最後再進行版面配置與路由設定
不過現在建這個componet很簡單了
Angular有一個樣板產生器的功能Schematics
Angular Material comes packaged with Angular CLI schematics to make creating Material applications easier
此樣板產生器架構在Angular Material與CDK
schematics官方提供了address-form 、navigation、dashboard、table、tree、drag-drop等基本樣版
在專案中到我們今天要用navigation
後面帶入自己定義component名稱
cd src/app/programs
ng generate @angular/material:nav trinav
可以發現schematics很貼心的幫我們import所需功能到app.module.ts
但因為我們已經把Angular Material包成一包Module統一收在一起
並不需要在個別import Matrial各功能,所以大可把app.module中import來自@angular/material
的都砍掉
接下來就可以來修改編排你的後台版面了
<mat-toolbar color="primary"> //把toolbar移到最上面
<button type="button" aria-label="Toggle sidenav" mat-icon-button (click)="toggleSideNav(drawer)">
<mat-icon aria-label="Side nav toggle icon">menu</mat-icon>
</button>
<span>AngularTri</span>
<span class="toolbar-seprator"></span>
<button mat-icon-button>
<mat-icon>message</mat-icon>
</button>
<button mat-icon-button>
<mat-icon>exit_to_app</mat-icon>
</button>
</mat-toolbar>
<mat-sidenav-container fixedInViewport="true">
<mat-sidenav #drawer class="sidenav" [attr.role]="(isHandset$ | async) ? 'dialog' : 'navigation'" [mode]="(isHandset$ | async) ? 'push ' : 'side'"
[opened]="!(isHandset$ | async)">
<mat-toolbar color="primary">Menu</mat-toolbar>
<mat-nav-list>
<a mat-list-item href="/tri001">Tri001</a>
<a mat-list-item href="/tri002">Tri002</a>
</mat-nav-list>
</mat-sidenav>
<mat-sidenav-content>
<router-outlet></router-outlet> //各個程式route搬到這裡
</mat-sidenav-content>
</mat-sidenav-container>
sidenav
的buttontoolbar
裡面的button的``ngIf```拿掉就會出現囉drawer.toggle()
可以自己改寫成toggleSideNav()
,利用MatDrawerToggleResult
偵測sidenav目前是open or close如果你覺得都不滿意的話,直接改寫toolbar與sidenav的擺放
設計好後,需要再調整Route,實作後會發現關鍵在CSS
多加了一個右邊的sidenav可以用來顯示登入者的基本資料
<mat-toolbar color="warn" class="header-toolbar">
<button type="button" aria-label="Toggle sidenav" mat-icon-button (click)="toggleSideNav(drawer)">
<mat-icon aria-label="Side nav toggle icon">menu</mat-icon>
</button>
<span>AngularTri</span>
<span class="toolbar-seprator"></span>
<span>{{programName}}</span>
<button mat-icon-button (click)="toggleSideNav(drawerRight)">
<mat-icon>face</mat-icon>
</button>
<button mat-icon-button>
<mat-icon>exit_to_app</mat-icon>
</button>
</mat-toolbar>
<mat-sidenav-container fixedInViewport="true">
<mat-sidenav #drawer position="start" mode="side" class="sidenav" opened>
<mat-toolbar color="primary" >
<span>Program</span>
<span>
<mat-icon>verified_user</mat-icon>
</span>
</mat-toolbar>
<mat-nav-list>
<a mat-list-item routerLink="./tri001" (click)="show('Tri001')">Tri001</a>
<a mat-list-item routerLink="./tri002" (click)="show('Tri002')">Tri002</a>
</mat-nav-list>
</mat-sidenav>
<mat-sidenav-content>
<router-outlet></router-outlet>
</mat-sidenav-content>
</mat-sidenav-container>
<mat-sidenav-container fixedInViewport="true">
<mat-sidenav #drawerRight position="end" mode="side" class="sidenavRight">
<mat-toolbar color="primary">
<span>基本資料</span>
<span>
<mat-icon>verified_user</mat-icon>
</span>
</mat-toolbar>
<mat-list>
<mat-list-item class="l-sub-section">
<mat-icon>code</mat-icon>
Peterhu2Tri
</mat-list-item>
<mat-list-item class="l-sub-section">
<mat-icon>account_circle</mat-icon>
三十天鐵人賽
</mat-list-item>
...
</mat-list>
</mat-sidenav>
</mat-sidenav-container>
programName = 'Tri001'; //預設頁面是第一隻程式
toggleSideNav(drawer: MatSidenav) {
drawer.toggle().then((result: MatDrawerToggleResult) => {
console.log('選單狀態:' + result);
});
show(item: string) {
this.programName = item;
}
.sidenav-container {
height: 100%;
}
.sidenav {
width: 200px;
position: fixed;
top: 64px;
left: 0;
}
//右邊的sidenav
.sidenavRight {
width: 250px;
position: fixed;
top: 64px;
}
//標頭toolbar
.header-toolbar {
padding: 0 16px 0 0;
position: fixed;
left: 0;
right: 0;
top: 0;
z-index: 10;
}
//選單toolbar
.menu-toolbar {
position: sticky;
top: 0;
z-index: 2;
}
.mat-drawer-content.mat-sidenav-content {
margin-top: 100px //因為固定了最上面的toolbar,所以讓contonet內容往下移
}
//分隔toolbar內的空間
.toolbar-seprator {
flex: 1 1 auto;
}
//list底線
.l-sub-section {
color: #333;
background-color: #e2effb;
padding: 3px;
margin-bottom: 8px;
display: table;
clear: both;
width: 100%;
box-sizing: border-box;
}
最後因為Route配置<router-outlet
改變了
需要做一些調整
<app-trinav></app-trinav>
const routes: Routes =
[{ path: '', redirectTo: '/tri001', pathMatch: 'full' }, //沒有指定path直接導入第一支程式
{ path: 'tri001', component: Tri001Component },
{ path: 'tri002', component: Tri002Component },
];
最後就可以看到成果啦
https://material.angular.io/components/sidenav/api
https://wellwind.idv.tw/blog/2017/12/24/angular-material-06-toolbar/
https://www.devglan.com/angular/material-sidenav-example
https://jonny-huang.github.io/angular/training/09_angular_router2/