官網:
https://meterial.io/components
優秀的Meterial design站點:
http://materialdesignblog.com/
並不是萬能的,都有約束條件。
優點:相容性好,可擴充套件性強,可測試性好,對主題的支援好。
缺點:元件不是特別豐富。
安裝:
//其它方式
$ sudo cnpm i --save @angular/[email protected]
$ sudo yarn add @angular/material --save
$ npm i @angular/material --save
安裝的版本是"@angular/material": "^7.1.0",
有個依賴要手動安裝
$ sudo yarn add @angular/[email protected] --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 |
Card適合圖文形式突出某一主題。https://material.angular.io/components/card/overview
<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 =[,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,];
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>