Angular data bnding 有以下幾種data binding方式:
String Interpolation
String Interpolation是可以將程式的變數輸出至template中顯示,使用方式是將變數或是function放在{{ 變數/function }},即可讓變數顯示在template上。
在class中,定義變數:
export class ServerComponent {
serverId: number = 10;
serverStatus: string = "offline";
getServerStatus() {
return this.serverStatus;
}
}
class中有serverId與serverStatus兩個變數,於是在template內可以使用string interpolation的方式來顯示,分別使用變數與function呈現:
<p>Serve with ID {{serverId}} is {{getServerStatus()}}</p>
將定義的變數放置在{{}}內,開啟網頁,即可看見結果將serverId與serverStatus顯示出來:
export class ServerComponent {
serverId: number = 10;
serverStatus: string = "offline";
getServerStatus() {
return this.serverStatus;
}
}
Attribute Binding
要以變數或是function執行結果來控制html element屬性時,可以使用attribute binging,例如要控制一個button是否被disabled,就可以透過button的其中一個屬性:disabled來達到控制的效果,我們只要想辦法控制disabled屬性的value即可達到這效果,因此可以透過attribute binding的方式來控制該屬性,attribute binding是以[屬性名稱] 中括弧將element的屬性包起來:例如以下template呈現方式:
<button class="btn btn-primary" [disabled]="!allowNewServer">Add server</button>
透過allowNewServer變數,來決定button是否被disabled,同時在程式內也得宣告變數allowNewServer才會有效:
export class ServersComponent {
allowNewServer = false;
constructor() {
setTimeout(() => {
this.allowNewServer = true;
}, 2000)
}
}
透過這程式,一開始宣告allowNewServer為false,在button的disabled上邏輯是!allowNewServer,等同於button的disable=true,表示button為不可點擊的狀態,這邊設了一個timeout,表示在兩秒後將allowNewServer的值改為true,讓button變為可點擊的狀態,因此,attribute binding即是將Html Element的屬性與Angular變數做結合,讓變數改變的同時,Html Element的屬性也一起改變,同時立即呈現到使用者眼前。
同理,要改變<p>的內文也用attribute binding的方式:
<p [innerText]="contentToDisplay"></p>
Event Binding
Event Binding是將Html Element的event與Angular內的function做綁定,讓html element在觸發特定事件時,可以執行Angular程式碼,舉例來說,像是button的onclick,要讓button的onclick觸發時,執行特定Angular程式碼。
Angular Event Binding的方式是用括弧將event名稱包起來,像是 (click)=functionName。
簡單做個測試:
在程式碼內新增一個string:serverCreationStatus,與一個function,當function觸發時,就改變serverCreationStatus並顯示在畫面上:
程式碼:
serverCreationStatus: string = 'No server was created.';
onCreateServer() {
this.serverCreationStatus = 'Server was created.';
}
template的部分:
<button class="btn btn-primary" [disabled]="!allowNewServer" (click)="onCreateServer()">Add server</button>
<p>{{serverCreationStatus}}</p>
這邊在button的click事件上綁定了onCreateServer事件,只要點擊button後就會執行onCreateServer 的function,並且改變serverCreatonStatus,畫面上的文字也會改變。
考慮一個情境,讓使用者輸入文字,作為serverName,每當使用變更input 內容時,就同時改變serverName的值。步驟依序如下:
新增input html element,
<input class="form-control" (input)="onUpdateServerName($event)" type="text">
並且綁定input事件,在使用者變更input content時,都會執行onUpdateServerName事件,同時傳入$event變數,$event變數是保留變數,主要是傳入當下觸發的事件資訊到onUpdateServerName function中。調整程式碼如下:
export class ServersComponent implements OnInit {
allowNewServer = false;
serverCreationStatus: string = 'No server was created.';
serverName: string = '';
constructor() {
setTimeout(() => {
this.allowNewServer = true;
}, 2000)
}
onCreateServer() {
this.serverCreationStatus = 'Server was created.';
}
onUpdateServerName($event: Event) {
console.log($event);
this.serverName = (<HTMLInputElement>$event.target).value;
}
ngOnInit() {
}
}
在onUpdateServerName function中,可以把$event印出來看看,可以看到詳細資訊,
export class ServersComponent implements OnInit {
allowNewServer = false;
serverCreationStatus: string = 'No server was created.';
serverName: string = '';
constructor() {
setTimeout(() => {
this.allowNewServer = true;
}, 2000)
}
onCreateServer() {
this.serverCreationStatus = 'Server was created.';
}
onUpdateServerName($event: Event) {
console.log($event);
this.serverName = (<HTMLInputElement>$event.target).value;
}
ngOnInit() {
}
}
到最下面可以看到value屬性,指的就是input輸入的內容,同時可以注意到_proto_是HTMLInputElement,表示觸發的html element型態。
在程式碼內因為要取得input element的內容,所以必須取用$event.target.value,即使用者輸入的內容,只是typescript會有警告,
原因是$event.target型態是EventTarget,EventTarget並沒有value的attribute的,要找到value,則必須把$event.target cast成 上面_proto_寫的HTMLInputElement型態,就可以成功拿到value值了。
所以要在程式碼調整成以下方式即可。
(<HTMLInputElement>$event.target).value;
取得使用者輸入資訊後,立刻指定給serverName,並且在template上加入{{serverName}},即會立刻輸出使用者輸入之內容。
Two-Way-Binding
前一個Event binging是使用者輸入資料時,可以讓輸入的資料與Angular內變數作連動,即資料變更時,Angular內的變數值也會跟著異動,只是若在程式內調整了變數的值,在使用者輸入介面上並不會呈現出來。
例如前一個event binding程式:
template:
<input class="form-control" (input)="onUpdateServerName($event)" type="text">
<p>Server Name: {{serverName}}</p>
typescript部分調整onUpdateServerName方法,變成在取得新的數值後,加入 " Edit"字串。
onUpdateServerName($event: Event) {
this.serverName = (<HTMLInputElement>$event.target).value;
this.serverName = this.serverName + ' Edit';
}
執行後會發現,input輸入資料時,Angular的變數有改變,但是Angular變數做修改時,input處的資料卻還是原本的資料。
Two-way binding則可以處理這部分的問題,當使用者在input內輸入資料時,Angular的資料會連動,同時Angular對該資料作處理與調整後,同時也會連動到前端input的資料上。
使用方式是[(ngModel="變數名稱")],在允許使用者輸入的element上可以使用,除了可以將使用者輸入帶到Angular程式邏輯外,Angular程式內所作的調整也會同步顯示到input上。
可以做個比較:
上面的input使用event bingind,下面的input使用two-way binding,再透過string interpolation觀察Angular內serverName變化,結果如下:
在第一個input1輸入數值1234後,Angular程式調整了serverName的內容變為1234 Edit,input1仍維持原本的輸入結果,input2則與Angular內的變數同步了,顯示1234 Edit。
template:
<input class="form-control" (input)="onUpdateServerName($event)" type="text">
<input type="text" class="form-control" [(ngModel)]="serverName">
<button class="btn btn-primary" [disabled]="!allowNewServer" (click)="onCreateServer()">Add server</button>
<p>Server Name: {{serverName}}</p>
typescript:
serverName: string = '';
onUpdateServerName($event: Event) {
this.serverName = (<HTMLInputElement>$event.target).value;
this.serverName = this.serverName + ' Edit';
}
要使用two-way databinding,一定要確認ngModel可以使用,所以要做的事情是確認app,modules.ts檔案內,imports陣列有加入FormsModule,同時也要將@angular/forms import到app.module.ts檔案中。
import { FormsModule } from '@angular/forms'; //別忘記將forms import進來
.
.
.
imports: [
BrowserModule,
FormsModule, //一定要import才能使用two-way data binding
HttpModule
],
我也在学这门课 坚持更新呀 你写得太好了!!
回覆刪除