官網:
https://meterial.io/components
優秀的Meterial design站點:
http://materialdesignblog.com/
並不是萬能的,都有約束條件。
優點:兼容性好,可擴展性強,可測試性好,對主題的支持好。
缺點:組件不是特別豐富。
安裝:
//其它方式
$ sudo cnpm i --save @angular/material@2.0.0-beta.7
$ sudo yarn add @angular/material --save
$ npm i @angular/material --save
安裝的版本是"@angular/material": "^7.1.0",
有個依賴要手動安裝
$ sudo yarn add @angular/cdk@6.4.6 --save
一、相關報錯
1、控制台報警告:Could not find Angular Material core theme。
在styles.scss中引入angular materail主題:
內建主題有這幾種:

可以用scss自定義主題。
2、ERROR Error: Found the synthetic listener @transform.start. Please include either "BrowserAnimationsModule" or "NoopAnimationsModule" in your application.
二、Material組件
1、SidebarComponent側邊欄導航:
https://material.angular.io/components/sidenav/overview
<mat-sidenav-container> <mat-sidenav #sidenav> <app-sidebar></app-sidebar> </mat-sidenav> <div class="site"> <header> <app-header></app-header> </header> <main> <button (click)="sidenav.open()">打開側邊欄</button> </main> <footer> <app-footer></app-footer> </footer> </div> </mat-sidenav-container>
根容器<mat-sidenav-container>
- over模式【默認】

- side模式

- push模式

- position="end"
<mat-sidenav #sidenav mode="push" position="end">
側邊欄跑右邊了,默認start。最多可以有2個側邊欄。
<mat-sidenav-container> <mat-sidenav #sidenav1 mode="push" position="end"> <app-sidebar></app-sidebar> </mat-sidenav> <mat-sidenav #sidenav2 mode="push" position="start"> <app-sidebar></app-sidebar> </mat-sidenav> <div class="site"> <header> <app-header></app-header> </header> <main> <button (click)="sidenav1.open()">打開右邊側邊欄</button> <button (click)="sidenav2.open()">打開左邊側邊欄</button> </main> <footer> <app-footer></app-footer> </footer> </div> </mat-sidenav-container>

- toogle方法:類似open
<mat-sidenav-container> <mat-sidenav #sidenav mode="side" > <app-sidebar></app-sidebar> </mat-sidenav> <div class="site"> <header> <app-header></app-header> </header> <main> <button (click)="sidenav.toggle()">打開側邊欄</button> </main> <footer> <app-footer></app-footer> </footer> </div> </mat-sidenav-container>
2、Toolbar完成頭部和尾部
https://material.angular.io/components/toolbar/overview
用於頭部,標題欄
顏色primary紫色,accent黃色,warn紅色。
主色:primary
配色:accent
用官方的material io 的COLOR TOOL可以調出合適的顏色。主色深紫,輔助色黃色效果如下。
1、居中用flex怎么實現?
![]()
在想居中元素兩邊都放了自動擴大充滿的元素。
在styles.scss中加入
.fill-remaining-space { // 使用 flexbox 填充剩余空間 // @angular/material 中的很多控件使用了 flex 布局 flex: 1 1 auto; }
<mat-toolbar color="primary"> <span class="fill-remaining-space"></span> <span>© strof 版權聲明</span> <span class="fill-remaining-space"></span> </mat-toolbar>
2、兩行內容怎么實現?

<mat-toolbar color="primary"> <mat-toolbar-row> <span class="fill-remaining-space"></span> <span>© starof 版權聲明</span> <span class="fill-remaining-space"></span> </mat-toolbar-row> <mat-toolbar-row> <span class="fill-remaining-space"></span> <span>這是第二行</span> <span class="fill-remaining-space"></span> </mat-toolbar-row> </mat-toolbar>
3、菜單button調出左邊sidebar
4、 用一個icon代替菜單2個文字
https://material.angular.io/components/icon/overview

使用圖標字體,基於字體的,好處占用資源小,矢量圖,內建material icon支持。
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<button mat-icon-button (click)="openSidebar()"> <mat-icon class="material-icons">menu</mat-icon> </button>

想要使用其它圖標直接,去https://material.io/tools/icons/ 找到圖標對應文字替換掉即可。
5、MatIcon也支持SVG圖標。
找SVG資源, http://iconfont.cn/ 阿里爸爸矢量圖標庫
把下載好的SVG放在項目的assets中。
最終效果:
constructor(private iconRegistry: MatIconRegistry, private sanitizer: DomSanitizer) { iconRegistry.addSvgIcon('gift', sanitizer.bypassSecurityTrustResourceUrl('assets/gift.svg')); }
<mat-icon svgIcon="gift"></mat-icon>
問題,每次使用一個新圖標都要注冊一遍。圖標分散在各個組件的constructor中,難以維護。
更好的做法:
在app下創建一個utils目錄,在utils里建一個svg.util.ts。
import { MatIconRegistry } from "@angular/material";
import { DomSanitizer } from "@angular/platform-browser";
export const loadSvgResources = (ir: MatIconRegistry, ds: DomSanitizer) => {
ir.addSvgIcon("gift", ds.bypassSecurityTrustResourceUrl("assets/gift.svg"));
};
不在組件的constructor里導入里,在core module里只加載一次。
export class CoreModule { constructor( @Optional() @SkipSelf() parent: CoreModule, //加上@SkipSelf()注解 ir: MatIconRegistry, ds: DomSanitizer ) { if (parent) { throw new Error("模塊已經存在,不能再次加載"); } loadSvgResources(ir, ds); } }
這樣其它頁面只要用就可以,解決了裝載資源分散的問題。
3、Input組件matInputModule
可以通過color取值warn,accent等來改變input輸入框的顏色。
可以通過floatLabel取值float,always,auto來改變Label顯示方式。
可以設置hintLabel或者<mat-hint>來添加更多提示信息。
可以通過給<mat-form-field>里的元素設置matSuffix指令來給輸入框添加后綴,設置matPrefix指令加前綴。
https://material.angular.io/components/form-field/overview
<mat-form-field class="example-full-width" color="warn" floatLabel="auto" hintLabel="Max 10 characters"> <input #input matInput placeholder="您的email"> <span matSuffix>@gmail.com</span> <mat-hint align="end">{{input.value?.length || 0}}/10</mat-hint> </mat-form-field>

4、Card組件和Button組件
mat-button |
Rectangular text button w/ no elevation |
mat-raised-button |
Rectangular contained button w/ elevation |
mat-flat-button |
Rectangular contained button w/ no elevation |
mat-stroked-button |
Rectangular outlined button w/ no elevation |
mat-icon-button |
Circular button with a transparent background, meant to contain an icon |
mat-fab |
Circular button w/ elevation, defaults to theme's accent color |
mat-mini-fab |
<mat-card class="example-card"> <mat-card-header> <mat-card-title>每日佳句</mat-card-title> <mat-card-subtitle>滿足感在於不斷的努力,而不是現有成就。全心努力定會勝利滿滿。</mat-card-subtitle> </mat-card-header> <img mat-card-image src="/assets/images/quote_fallback.jpg" alt=""> <mat-card-content> Satisfaction lies in the effort, not in the attainment. Full effort is full victory. </mat-card-content> </mat-card>

5、List
https://material.angular.io/components/list/overview
包括都行列表,帶圖標列表,帶頭像列表,密集列表(dense list)和多段列表。
分為<mat-list> 和<mat-nav-list>
在側滑菜單中使用List。
matNavList鼠標hover上去會有高亮效果。
<mat-nav-list> <h3 mat-subheader>項目</h3> <mat-list-item> <mat-icon mat-list-icon svgIcon="projects"></mat-icon> <h4 mat-line>項目首頁</h4> <p mat-line mat-subheader> 查看您的所有項目</p> </mat-list-item> <h3 mat-subheader>日歷</h3> <mat-list-item> <mat-icon mat-list-icon svgIcon="month"></mat-icon> <h4 mat-line>月視圖</h4> <p mat-line mat-subheader> 按月查看您的任務</p> </mat-list-item> <mat-list-item> <mat-icon mat-list-icon svgIcon="week"></mat-icon> <h4 mat-line>周視圖</h4> <p mat-line mat-subheader> 按周查看您的任務</p> </mat-list-item> <mat-list-item> <mat-icon mat-list-icon svgIcon="day"></mat-icon> <h4 mat-line>日視圖</h4> <p mat-line mat-subheader> 按天查看您的任務</p> </mat-list-item> </mat-nav-list>

Dense list會讓列表的字體shrink來顯示更多內容。用法<mat-nav-list dense>。
把日式圖的圖標改變成當天的日前,在svg.util.ts中加入提前准備好的30天日期day1.svg到day3-.svg.
import { MatIconRegistry } from "@angular/material";
import { DomSanitizer } from "@angular/platform-browser";
export const loadSvgResources = (ir: MatIconRegistry, ds: DomSanitizer) => {
const imgDir = "assets/img";
const sidebarDir = `${imgDir}/sidebar`;
const dayDir = `${imgDir}/days`;
ir.addSvgIcon(
"day",
ds.bypassSecurityTrustResourceUrl(`${sidebarDir}/day.svg`)
);
ir.addSvgIcon(
"month",
ds.bypassSecurityTrustResourceUrl(`${sidebarDir}/month.svg`)
);
ir.addSvgIcon(
"project",
ds.bypassSecurityTrustResourceUrl(`${sidebarDir}/project.svg`)
);
ir.addSvgIcon(
"projects",
ds.bypassSecurityTrustResourceUrl(`${sidebarDir}/projects.svg`)
);
ir.addSvgIcon(
"week",
ds.bypassSecurityTrustResourceUrl(`${sidebarDir}/week.svg`)
);
const days =[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];
days.forEach((d)=>{
ir.addSvgIcon(
`day${d}`,
ds.bypassSecurityTrustResourceUrl(`${dayDir}/day${d}.svg`)
);
});
};
在sidebar.component.ts中引入一個類庫day-fns。
npm uninstall --save date-fns //先安裝date-fns npm install --save-dev @types/date-fns //再date-fns針對typescript也可以使用的類型

import { Component, OnInit } from '@angular/core';
import {getDate} from 'date-fns'; //getDate取得是一個月的幾號
@Component({
selector: 'app-sidebar',
templateUrl: './sidebar.component.html',
styleUrls: ['./sidebar.component.scss']
})
export class SidebarComponent implements OnInit {
today = 'day';
constructor() { }
ngOnInit() {
this.today=`day${getDate(new Date())}`; //today對應icon的名字
}
}
模版中icon對應到today。

6、GridList
<mat-grid-list cols="8" rowHeight="1:1"> <mat-grid-tile colspan="2"> 1 </mat-grid-tile> <mat-grid-tile> 2 </mat-grid-tile> <mat-grid-tile> 3 </mat-grid-tile> <mat-grid-tile> 4 </mat-grid-tile> <mat-grid-tile rowspan="2"> 5 </mat-grid-tile> <mat-grid-tile> 6 </mat-grid-tile> <mat-grid-tile> 7 </mat-grid-tile> <mat-grid-tile> 8 </mat-grid-tile> <mat-grid-tile> 9 </mat-grid-tile> <mat-grid-tile> 10 </mat-grid-tile> <mat-grid-tile> 11 </mat-grid-tile> <mat-grid-tile> 12 </mat-grid-tile> <mat-grid-tile> 13 </mat-grid-tile> <mat-grid-tile> 14 </mat-grid-tile> </mat-grid-list>

注冊頁面頭像列表可以用GridList實現。
7、dialog
https://material.angular.io/components/dialog/overview
對話框很特殊,和menu一樣需要在模塊中的entryComponents中聲明。
由於它們是需要事先完全隱藏,或者隱藏一部分。一開始模塊加載的時候是看不到dialog的,點擊按鈕才能彈出。對於這種情況,需要一個預加載,就需要放在模塊的entryComponents中。
1、從調用者向Dialog傳遞數據
傳遞數據:
不能像其它組件一樣,通過路由去傳遞數據。需要從它的調用者去寫。
在按鈕的click事件中寫:
const dialogRef = dialog.open(YourDialog, {data:'Your data'});
接收數據:
在Dialog的構造中注入MD_DIALOG_DATA就可以取得數據。
constructor(@Inject(MAT_DIALOG_DATA) private data: any) { }
2、在Dialog把數據往回傳,傳給調用者。
//注入MatDialogRef constructor(@Inject(MAT_DIALOG_DATA) private data: any, public dialogRef: MatDialogRef<NewProjectComponent>, ) { } //在點擊保存按鈕時候發送數據 onSave() { this.dialogRef.close('I received your message'); }
//調用者open的時候拿到一個引用,注冊afterClosed事件返回一個Observable openNewProjectDialog() { // this.dialog.open(NewProjectComponent,{data:'this is a dialog'}); const dialogRef = this.dialog.open(NewProjectComponent, { data: "this is a dialog" }); dialogRef.afterClosed().subscribe((result)=>{ console.log(result); }); }
3、Dialog樣式支持主題
//注入OverlayContainer constructor(@Inject(MAT_DIALOG_DATA) private data: any, public dialogRef: MatDialogRef<NewProjectComponent>, private oc: OverlayContainer) { } //通過傳入dark來切換class ngOnInit() { console.log(JSON.stringify(this.data)); this.oc.themeClass = this.data.dark ? 'myapp-dark-theme' : 'null'; }
報錯:ERROR in src/app/project/new-project/new-project.component.ts(18,13): error TS2339: Property 'themeClass' does not exist on type 'OverlayContainer'.
參考:
https://gist.github.com/tomastrajan/ee29cd8e180b14ce9bc120e2f7435db7
8、autoComplete
https://material.angular.io/components/autocomplete/overview

<form class="example-form"> <mat-form-field class="example-full-width"> <input type="text" placeholder="Assignee" aria-label="Assignee" matInput [formControl]="myControl" [matAutocomplete]="auto"> <mat-autocomplete #auto="matAutocomplete" [displayWith]="displayFn"> <mat-option *ngFor="let option of filteredOptions | async" [value]="option"> {{option.name}} </mat-option> </mat-autocomplete> </mat-form-field> </form>
displayWith傳入一個函數,指明具體怎樣顯示
displayFn(user?: User): string | undefined { return user ? user.name : undefined; }
9、menu
<button mat-button [matMenuTriggerFor]="menu">Menu</button> <mat-menu #menu="matMenu"> <button mat-menu-item>Item 1</button> <button mat-menu-item>Item 2</button> </mat-menu>
10、復選框,單選組件和下拉框
<mat-checkbox>和<mat-radio>和<mat-select>
checkbox還要chenged事件處理
<mat-checkbox [checked]="item.completed" class="status"> </mat-checkbox>
<div class="content" mat-line [ngClass]="{'completed':item.completed}"> <span [matTooltip]="item.desc">{{item.desc}}</span> </div>
11、DatePicker
https://material.angular.io/components/datepicker/overview
<mat-form-field> <input matInput [matDatepicker]="picker" placeholder="Choose a date"> <mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle> <mat-datepicker #picker></mat-datepicker> </mat-form-field>

