官網:css
https://material.io/design/html
https://meterial.io/componentsgit
優秀的Meterial design站點:github
http://materialdesignblog.com/typescript
並非萬能的,都有約束條件。npm
優勢:兼容性好,可擴展性強,可測試性好,對主題的支持好。api
缺點:組件不是特別豐富。markdown
安裝:app
//其它方式
$ sudo cnpm i --save @angular/material@2.0.0-beta.7async
$ 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
一、控制檯報警告:Could not find Angular Material core theme。
在styles.scss中引入angular materail主題:
內建主題有這幾種:
能夠用scss自定義主題。
二、ERROR Error: Found the synthetic listener @transform.start. Please include either "BrowserAnimationsModule" or "NoopAnimationsModule" in your application.
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>
側邊欄跑右邊了,默認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>
<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>
https://material.angular.io/components/toolbar/overview
用於頭部,標題欄
顏色primary紫色,accent黃色,warn紅色。
主色:primary
配色:accent
用官方的material io 的COLOR TOOL能夠調出合適的顏色。主色深紫,輔助色黃色效果以下。
在想居中元素兩邊都放了自動擴大充滿的元素。
在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>
<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>
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/ 找到圖標對應文字替換掉便可。
把下載好的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); } }
這樣其它頁面只要用就能夠,解決了裝載資源分散的問題。
能夠經過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>
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>
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。
<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實現。
https://material.angular.io/components/dialog/overview
對話框很特殊,和menu同樣須要在模塊中的entryComponents中聲明。
因爲它們是須要事先徹底隱藏,或者隱藏一部分。一開始模塊加載的時候是看不到dialog的,點擊按鈕才能彈出。對於這種狀況,須要一個預加載,就須要放在模塊的entryComponents中。
傳遞數據:
不能像其它組件同樣,經過路由去傳遞數據。須要從它的調用者去寫。
在按鈕的click事件中寫:
const dialogRef = dialog.open(YourDialog, {data:'Your data'});
接收數據:
在Dialog的構造中注入MD_DIALOG_DATA就能夠取得數據。
constructor(@Inject(MAT_DIALOG_DATA) private data: any) { }
//注入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); }); }
//注入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
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; }
<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>
<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>
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>