先前在說明 Angular 2 的架構時有約略提到數據綁定的方式,接著就讓我們學學如何寫模板 (template) ,如何顯示數據和事件綁定。那為甚麼要學模板的寫法呢?以及模板到底可以幹嗎?我們看到的網站都是 HTML 的顯示,但是 HTML 是死的,要做出互動傳統上必須靠 JavaScript,但是 JS 控制 HTML

數據綁定小複習

  • Interpolation
  • One Way Binding
  • Two Way Binding
  • Event Binding

概觀

語法

在 Anugular 2 中:

  • One Way Binding:從看到的目標綁定數據來源用的是:
    • (target) = "statement"
    • on-target = "statement"
  • One Way Binding:從數據來源綁定看到的目標用的是:
    • [target] = "expression"
    • bind-target = "expression"
  • Two Way Binding:數據端跟視覺端可以互相綁定用的是:
    • [(target)] = "expression"
    • bindon-target = "expression"

範例

我們可以再 Component 中宣告自己的標籤

<!-- Normal HTML -->
<div class="special">Mental Model</div>
<!-- Wow! A new element! -->
<hero-detail></hero-detail>

Component 中的 isValidfalse 的時候按鈕鎖住。

<!-- Bind button disabled state to `isValid` property -->
<button [disabled]="!isValid">Save</button>

可以直接綁定連結

<img [src]="imageUrl">

可以綁定特性

<div [ngClass]="classes">[ngClass] binding to the classes property</div>

綁定 Attribute、class、style

用途

當我們想針對 HTML 的屬性、類別、風格做改變時,透過 Angular 特性 (property) 綁定的方式,可以輕鬆一據綁定的數據做改變,比方說想要達成按下按鈕顏色改變,就可以透過這種方式,比起傳統的方式,增加不少便利性。

Attribute binding (屬性綁定)

針對 HTML 物件的屬性作綁定,可以依據綁定的變數數值變化而改變屬性。

<table border=1>
  <!--  expression calculates colspan=2 -->
  <tr><td [attr.colspan]="1 + 1">One-Two</td></tr>

<tr><td>Five</td><td>Six</td></tr>
</table>

Class binding

當綁定的數值為 true 時顯示 classfalse 移除 class

<!-- toggle the "special" class on/off with a property -->
<div [class.special]="isSpecial">The class binding is special</div>

<!-- binding to class.special trumps the class attribute –>
<div class="special"
[class.special]="!isSpecial">This one is not so special</div>

Style binding

一樣的邏輯也可以用在 style

<button [style.color] = "isSpecial ? 'red': 'green'">Red</button>
<button [style.background-color]="canSave ? 'cyan': 'grey'" >Save</button>

事件綁定 (Event binding)

一般的事件綁定
tempalte:

<button (click)="onSave()">Save</button>

Component:

@Component({
    ...
})
export class AppComponent {
    onSave(): void{
        ...
    }
}

這種一般的用法,可以拿來做按鈕呼叫 API 提交表單等等,不需要做 HTML Element 變化的互動。

也可以是自訂的事件綁定,這時候我們用 Angular EventEmitter
我們這樣定義觸發事件:

deleteRequest = new EventEmitter<Hero>();

delete() {
this.deleteRequest.emit(this.hero);
}

模板:

<div>
      ...
  <button (click)="delete()">Delete</button>
      ...
</div>
<hero-detail (deleteRequest)="deleteHero($event)" [hero]="currentHero"></hero-detail>

delete() 執行,會觸發 deleteRequest 產生的 EvevntEmitter 物件製造出 Hero ,接者 <hero-detail> 會跟著 deleteRequest 事件觸發的改變而改變。

數據綁定

Interpolation

基本就是在 html template 裡面加上 { { } },中間包住想要顯示的變數,而變數則是宣告在 app.component.ts 裡面。
來看看範例:

// app.component.ts
import {Component} from 'angular2/core';
@Component({
  selector: 'my-app',
  templateUrl: 'app.component.html',
  styleUrls: ['app.component.css']
})
export class AppComponent {
  title = 'Tour of Heroes';
  myHero = 'Windstorm';
}
// app.component.html
  <h1>{{title}}</h1>
  <h2>My favorite hero is: {{myHero}}</h2>

會顯示成這樣:
因為是在同個 Component,當 Angular 在 Template 中偵測到 { { } } 的時候, Class 裡的變數會直接被放到 { { } } 裡面。當變數值發生改變時也會跟著更新顯示,數值重新渲染顯示是發生在與視圖相關的某些異步事件之後,例如點擊、勾選、呼叫 XHR。

還可以拿來這樣用:

<!-- "The sum of 1 + 1 is 2" -->
<p>The sum of 1 + 1 is {{1 + 1}}</p>

Two Way Binding

顧名思義,就是前後都能彼此控制對方,更白話一點就是程式可以控制顯示,顯示的地方也可以利用按鈕、輸入等方式改變數據。
可能就會長得像這樣;

<my-sizer [(size)]="fontSizePx"></my-sizer>
<div [style.font-size.px]="fontSizePx">Resizable Text</div>

my-sizer 雙向綁定,不管是數據來源改變還是介面由使用者改變,而下面的的 div 則會受到改變。

NgModal

當有 InputSelect 的時候 NgModal 可以有效連結綁定 Component 的數據。
直接來看看範例吧:

<div>
  <h4>Select Account</h4>
  <select [(ngModel)]="selectedAccount" (ngModelChange)="selectAccount()">
    <option *ngFor="let account of accounts" [ngValue]="account">{{account.name}}</option>
  </select>
</div>

*ngFor 會顯示 accounts: array 中所有的 account,被選取的選項,透過 [ngValue] 回傳值,因為<select> 已經和 [(ngModal)] 綁定,所以 [(ngModal)] 得到 [ngValue] 的值,並和 Component 中的 selectedAccount 做雙向綁定。
甚麼意思呢,就是說你拉下選單選某個選項時候, Component 中的 selectedAccount 也跟著選項改變他的值。