angular2-模板驅動表單
app.module.ts 導入 FormsModule
import { NgModule } from ‘@angular/core‘; import { BrowserModule } from ‘@angular/platform-browser‘; import { FormsModule } from ‘@angular/forms‘; import { AppComponent } from ‘./app.component‘; import { HeroFormComponent } from ‘./hero-form.component‘; @NgModule({ imports: [ BrowserModule, FormsModule], declarations: [ AppComponent, HeroFormComponent ], bootstrap: [ AppComponent ] }) export class AppModule { }
如果某個組件、指令或管道是屬於imports
中所導入的某個模塊的,那就不能再把它再聲明到本模塊的declarations
數組中。 如果它是你自己寫的,並且確實屬於當前模塊,才應該把它聲明在declarations
數組中。
container
、form-group
、form-control
和btn
類來自 Twitter Bootstrap。純粹是裝飾。 我們使用 Bootstrap 來美化表單。
Angular 不需要container
、form-group
、form-control
和btn
類, 或者外部庫的任何樣式。Angular 應用可以使用任何 CSS 庫…… ,或者啥都不用
<form #heroForm="ngForm">
<div class="form-group"> <label for="name">Name</label> <input type="text" class="form-control" id="name" required [(ngModel)]="model.name" name="name"> </div> <div class="form-group"> <label for="alterEgo">Alter Ego</label> <input type="text" class="form-control" id="alterEgo" [(ngModel)]="model.alterEgo" name="alterEgo"> </div> <div class="form-group"> <label for="power">Hero Power</label> <select class="form-control" id="power" required [(ngModel)]="model.power" name="power"> <option *ngFor="let pow of powers" [value]="pow">{{pow}}</option> </select> </div>
NgForm:
什麽是NgForm
指令? 但我們明明沒有添加過NgForm指令啊!
Angular替你做了。Angular會在<form>
標簽上自動創建並附加一個NgForm
指令。
NgForm
指令為form
增補了一些額外特性。 它會控制那些帶有ngModel
指令和name
屬性的元素,監聽他們的屬性(包括其有效性)。 它還有自己的valid
屬性,這個屬性只有在它包含的每個控件都有效時才是真
<input>
標簽還添加了name
屬性 (attribute),並設置為 "name",表示英雄的名字。 使用任何唯一的值都可以。
當在表單中使用[(ngModel)]
時,必須要定義name
屬性。
內部,Angular 創建了一些FormControl
,並把它們註冊到NgForm
指令,再將該指令附加到<form>
標簽。 註冊每個FormControl
時,使用name
屬性值作為鍵值
-
每個 input 元素都有
id
屬性,label
元素的for
屬性用它來匹配到對應的輸入控件。 -
每個 input 元素都有
name
屬性,Angular 表單用它註冊控件。
通過 ngModel 跟蹤修改狀態與有效性驗證
ngModel
可以獲得比僅使用雙向數據綁定更多的控制權。它還會告訴我們很多信息:用戶碰過此控件嗎?它的值變化了嗎?數據變得無效了嗎?
NgModel 指令不僅僅跟蹤狀態。它還使用特定的 Angular CSS 類來更新控件,以反映當前狀態。 可以利用這些 CSS 類來修改控件的外觀,顯示或隱藏消息。
狀態 |
為真時的 CSS 類 |
為假時的 CSS 類 |
---|---|---|
控件被訪問過。 |
ng-touched |
ng-untouched |
控件的值變化了。 |
ng-dirty |
ng-pristine |
控件的值有效。 |
ng-valid |
ng-invalid |
例子:往姓名<input>
標簽上添加名叫 spy 的臨時模板引用變量, 然後用這個 spy 來顯示它上面的所有 CSS 類
<input type="text" class="form-control" id="name" required [(ngModel)]="model.name" name="name" #spy> <br>TODO: remove this: {{spy.className}}
- 查看輸入框,但別碰它:
- 點擊輸入框,然後點擊輸入框外面。:
- 在名字的末尾添加些斜杠。
- 刪除名字。
(ng-valid
| ng-invalid
)這一對是我們最感興趣的。當數據變得無效時,我們希望發出強力的視覺信號, 還想要標記出必填字段。可以通過加入自定義 CSS 來提供視覺反饋
輸入框的左側添加帶顏色的豎條,用於標記必填字段和無效輸入
添加兩個樣式來實現這一效果
.ng-valid[required], .ng-valid.required { border-left: 5px solid #42A948; /* green */ } .ng-invalid:not(form) { border-left: 5px solid #a94442; /* red */ }
顯示和隱藏驗證錯誤信息
//template
<label for="name">Name</label> <input type="text" class="form-control" id="name" required [(ngModel)]="model.name" name="name" #name="ngModel"> <div [hidden]="name.valid || name.pristine" class="alert alert-danger"> Name is required </div>
<button type="button" class="btn btn-default" (click)="newHero()">New Hero</button>
//ts
newHero() { this.model = new Hero(42, ‘‘, ‘‘); }
當控件是有效的 (valid) 或全新的 (pristine) 時,隱藏消息。 “全新的”意味著從它被顯示在表單中開始,用戶還從未修改過它的值。
input 創建了名叫name
的變量,並且賦值為 "ngModel"( 指令的 exportAs 屬性告訴 Angular 如何鏈接模板引用變量到指令。 這裏把name
設置為ngModel
是因為ngModel
指令的exportAs
屬性設置成了 “ngModel”)
點擊 New Hero 按鈕,表單被清空了。 輸入框左側的必填項豎條是紅色的.
問題:
輸入名字,再次點擊 New Hero 按鈕。 這次,出現了錯誤信息!為什麽?我們不希望顯示新(空)的英雄時,出現錯誤信息。
使用瀏覽器工具審查這個元素就會發現,這個 name 輸入框並不是全新的。 表單記得我們在點擊 New Hero 前輸入的名字。 更換了英雄並不會重置控件的“全新”狀態
我們必須清除所有標記,在調用 newHero()
方法後調用表單的 reset()
方法即可 (click)="newHero(); heroForm.reset()"
提交表單
<form (ngSubmit)="onSubmit()" #heroForm="ngForm">
<button type="submit" class="btn btn-success" [disabled]="!heroForm.form.valid">Submit</button>
切換兩個表單區域(額外的獎勵)
把表單包裹進<div>
中,再把它的hidden
屬性綁定到HeroFormComponent.submitted
屬性。
<div [hidden]="submitted"> <h1>Hero Form</h1> <form (ngSubmit)="onSubmit()" #heroForm="ngForm"> </form> </div>
開始就是可見的,因為submitted
屬性是 false,直到提交了這個表單。
submitted = false;
onSubmit() { this.submitted = true; }
當點擊 Submit 按鈕時,submitted
標誌會變成 true,並且表單像預想中一樣消失了
當表單處於已提交狀態時,需要顯示一些別的東西。 在剛剛寫的<div>
包裝下方,添加下列 HTML 語句:
<div [hidden]="!submitted"> <div class="row"> <div class="col-xs-3">Name</div> <div class="col-xs-9 pull-left">{{ model.name }}</div> </div> <button class="btn btn-primary" (click)="submitted=false">Edit</button> </div>
當點Edit按鈕時,這個只讀塊消失了,可編輯的表單重新出現了
angular2-模板驅動表單