Angular UI:Angular Material2

Material Design for Angular

Angular 模組 最後我們只加了幾行 CSS 樣式,由一開始練習至此感覺起來這種網頁效果十幾年前用記事本就可以做到了,那花時間學這個幹嘛?我們過去會的技術能不能繼續沿用下來?首當其衝的就是 jQuery for Angular 的問題。

其實筆者並沒用過 jQuery、Ajax,對於 JavaScript、CSS 也都是上網查詢別人寫好的範例來改,過去都是在開發視窗程式,網頁的經驗是停留在 ASP.NET 2.0 時代,利用 Visual Studio .NET,透過滑鼠拖拉產生千篇一律的畫面,再加上 C# 撰寫邏輯來產生網站。
說了這個多只是想告訴大家筆者是一個網路開發的初學者,站在這個角度來分享,身為後追者的我如何利用 Angular 來快速追趕上那些有多年開發經驗的人,至少能看到前方的車尾燈,畢竟在職場上客戶不會因為不同的資歷而有不同的評分標準,只會考慮誰能解決他的問題,老闆也不會讓你花幾年的時間慢慢磨練。
網路上其實已經有很多非常深入的文章,所以後續內容會著重在怎麼用以及如何善用 Angular 的優勢

我們開啟官方網站的資源頁面 https://angular.io/resources 一開始提到過上面有推薦一些開發工具,今天我們要來看的是官方所推薦的模組化元件-Angular Material2
img
我們依照 官方安裝教學步驟 來安裝。

安裝 Angular Material 與 Angular CDK

透過下列指令來安裝
npm install --save @angular/material @angular/cdk
img

如果大家安裝有遇到權限不足的錯誤訊息,甚至出現要求以系統管理員身分重新安裝時,可以嘗試把專案內的 package-lock.json 檔刪除後再重新安裝試試,npm 5.0 增加了 lock 機制。
img

安裝 Angular Animations 動畫模組

安裝指令
npm install --save @angular/animations

目前筆者使用的 CLI 版本為 1.3.2,專案建置時便會同時安裝動畫模組,但是預設並沒有將模組註冊。

將 動畫模組(BrowserAnimationsModule) 註冊到專案的 啟動模組(AppModule) 內。

app.module.ts
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
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { Page1Component } from './page1/page1.component';
import { Page2Component } from './page2.component';
import { Page3Component } from './page3.component';
import { Page404Component } from './page404/page404.component';
import { OperationModule } from './operation/operation.module';

@NgModule({
declarations: [
AppComponent,
Page1Component,
Page2Component,
Page3Component,
Page404Component
],
imports: [
BrowserModule,
AppRoutingModule,
BrowserAnimationsModule,
OperationModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }

匯入要使用的元件模組

說成 元件模組 是因為 Angular Material2 特別將每個元件(Component)都用一個獨立的模組(NgModule)包覆起來,這樣就不會連沒使用到的元件都一起打包到專案內,造成編譯後的檔案太大。
因為目前還沒決定要使用那些元件,所以暫時不先加入,後面有使用時再說明,但是官方文件提出一個很好的元件管理方式-建立一個模組來集中管理有用到的元件,有元件需要使用時再將它加入到該元件所依附的模組內。
執行下面安裝指令建立一個 CustomMaterialModule,帶上 --flat 參數讓 CLI 不要建立資料夾,因為不確定那些模組會使用,所以我們將檔案放置在最外層 src\app 底下。
ng g m customMaterial --flat
img

文件下方特別提到元件模組需加入在 BrowserModule 之後,也就是使用時除了要註冊到模組的 imports 屬性,如果 imports 屬性包含 BrowserModule 時需要將 CustomMaterialModule 放置在它的後面。
由此也可說明 imports 屬性具有順序性,它會依序處理。

匯入樣式

依官方文件將下列語法加到 src\styles.scss 內。
@import "~@angular/material/prebuilt-themes/indigo-pink.css";
不過我們從此路徑去搜尋就會發現,Angular Material2 總共提供了下列幾種配色的樣式:
deeppurple-amber.css
indigo-pink.css
pink-bluegrey.css
purple-green.css
img
開啟 src\styles.scss,將所有樣式都先加入,並選擇一個,剩餘的都先註解起來。

styles.scss
1
2
3
4
5
6
7
8
9
10
11
12
13
14
/* You can add global styles to this file, and also import other style files */

/* Angular Material2 Themes */
// @import "~@angular/material/prebuilt-themes/deeppurple-amber.css";
// @import "~@angular/material/prebuilt-themes/indigo-pink.css";
@import "~@angular/material/prebuilt-themes/pink-bluegrey.css";
// @import "~@angular/material/prebuilt-themes/purple-green.css";


P {
border: 1px dashed red;
margin: 8px;
}

安裝手勢操作的套件 HammerJS

安裝指令如下:
npm install --save hammerjs
img
hammerjs import 到程式的進入點(entry point),我們將下列語法加入至 src\main.ts
import 'hammerjs';

main.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';

import { AppModule } from './app/app.module';
import { environment } from './environments/environment';
import 'hammerjs';

if (environment.production) {
enableProdMode();
}

platformBrowserDynamic().bootstrapModule(AppModule);

(選擇性) 安裝圖示套件 Material Icons

Angular Material2 的圖示元件為 md-icon,我們在 首頁(src\index.html) 加入下面連結。
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">

index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<!doctype html>
<html lang="en">

<head>
<meta charset="utf-8">
<title>FirstApp</title>
<base href="/">

<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
</head>

<body>
<app-root></app-root>
</body>

</html>

測試

開啟 https://material.angular.io/components 頁面可以看到網頁展示了 Angular Material2 元件效果,同時也提供設定與使用說明。
md-icon 為例,選擇 Icon 元件頁籤,點選內容的 API 內容,可以看到該模組名稱為 MdIconModule,開起 src\app\custom-material.module.ts 並將 MdIconModule 加到 imports 以及 exports 屬性內。

custom-material.module.ts
1
2
3
4
5
6
7
8
9
import { NgModule } from '@angular/core';
import { MdIconModule } from '@angular/material';

@NgModule({
imports: [MdIconModule],
exports: [MdIconModule]
})
export class CustomMaterialModule { }

嘗試在 Page1Component 放入一些圖示:
因為 Page1Component 使用 CustomMaterialModule 內的 MdIconModule,所以必須將 CustomMaterialModule 註冊到 Page1Component 所屬的模組(AppModule)內,開啟並編輯 src\app\app.module.ts

app.module.ts
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
32
33
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { Page1Component } from './page1/page1.component';
import { Page2Component } from './page2.component';
import { Page3Component } from './page3.component';
import { Page404Component } from './page404/page404.component';
import { OperationModule } from './operation/operation.module';
import { CustomMaterialModule } from './custom-material.module';

@NgModule({
declarations: [
AppComponent,
Page1Component,
Page2Component,
Page3Component,
Page404Component
],
imports: [
BrowserModule,
AppRoutingModule,
BrowserAnimationsModule,
CustomMaterialModule,
OperationModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }

src\app\page1\page1.component.html 內加入一些圖示,如下面範例:

page1.component.htmls
1
2
3
4
5
6
7
8
9
10
<p>
page1 works!
<app-opt1></app-opt1>
<br>
<md-icon>home</md-icon>
<md-icon>done</md-icon>
<md-icon>delete</md-icon>
<md-icon>email</md-icon>
</p>

執行並切到 Page1 頁籤時可以看到畫面上確實出現了圖示。
img

圖示及其名稱可參閱 https://material.io/icons/ 查詢

區域網路

其實圖示是連結到 https://fonts.googleapis.com/ 網站來下載圖示檔,對於開放外部使用的網站來說可以減省傳輸流量,但是如果是在企業內部使用,有可能就不見得可以連結到外部網站,因此也我們需要能夠將圖示字型放置到所部屬的伺服器,以免網頁無法呈現圖示。

方法1:下載圖示字型

開啟 https://google.github.io/material-design-icons/,在網頁上提到官方提供圖示字型下載連結 material-design-icons-master.zip
img
img
解壓縮後將 iconfont 資料夾複製到 src\assets 資料夾下。
img
修改 src\index.html 內的連結路徑,重新執行圖示應該也可以正常顯示,但是圖示來源已經改成專案目錄。

index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<!doctype html>
<html lang="en">

<head>
<meta charset="utf-8">
<title>FirstApp</title>
<base href="/">

<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
<!-- <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet"> -->
<link href="./assets/iconfont/material-icons.css" rel="stylesheet">
</head>

<body>
<app-root></app-root>
</body>

</html>

img

開啟 .angular-cli.json 可以從 apps 區塊內看到一個assets 的設定值,預設指定了 assets 資料夾與 favicon.ico 網站圖示,Angular CLI 在編譯時會將 assets 內所指定的檔案或資料夾全部複製到輸出路徑("outDir": "dist"),因此我們可以將要連同網站一起佈署的檔案加進去,編譯時就會一起複製過去。
img

方法2:透過 npm 安裝

透過下列指令安裝,安裝時等待時間會比較久
npm install --save material-design-icons
img
開啟 src\styles.scss 加入下列語法:
@import '~material-design-icons/iconfont/material-icons.css';

styles.scss
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/* You can add global styles to this file, and also import other style files */

/* Angular Material2 Themes */
// @import "~@angular/material/prebuilt-themes/deeppurple-amber.css";
// @import "~@angular/material/prebuilt-themes/indigo-pink.css";
@import "~@angular/material/prebuilt-themes/pink-bluegrey.css";
// @import "~@angular/material/prebuilt-themes/purple-green.css";

/* Material Design Icon */
@import '~material-design-icons/iconfont/material-icons.css';

P {
border: 1px dashed red;
margin: 8px;
}

src\index.html 的連結拿掉後重新執行,正常應該圖示也會顯示。

index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<!doctype html>
<html lang="en">

<head>
<meta charset="utf-8">
<title>FirstApp</title>
<base href="/">

<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
<!-- <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet"> -->
<link href="./assets/iconfont/material-icons.css" rel="stylesheet">
</head>

<body>
<app-root></app-root>
</body>

</html>

img

[**first-app_2017-09-01.zip**](/uploads/first-app_2017-09-01.zip)