在angular2 form表單中咱們須要瞭解表單數據綁定、數據驗證、數據提交等內容,在下面的示例中並無實際提交到後臺,這部份內容在從此webapi中加以練習。html
<form (ngSubmit)="onSubmit(planetForm.value)" #planetform="ngForm">html5
</form>web
這裏是一個空的表單ngSubmit是一個事件,用於提交數據,數據則是整個form表單的內容,一般狀況下咱們的表單會綁定到咱們的一個model中,那麼提交的數據最後也是以json格式返回到後臺來處理。json
在表單中咱們可使用標準的html5控件來處理用戶輸入。bootstrap
<div class="form-group">api
<label class="col-xs-4 control-label" for="id">id : </label>promise
<div class="col-xs-8">angular2
<input type="text" style="width: 300px" class="form-control" required異步
[(ngModel)]="myPlanet.id"編輯器
ngControl="id"
#planetid="ngForm">
<div [hidden]="planetid.valid || planetid.pristine" class="alert alert-danger">
The Name of green car is required !
</div>
</div>
</div>
這個一個表單輸入的內容其中使用的是bootstrap的表單樣式,在input中咱們使用[(ngModel)](注意大小寫)實現雙向綁定,ngControl用於檢測數據變化對應的是model中的字段,設置input的變量爲ngForm來告訴angular 這個輸入是這個表單內容。在vs中因爲默認設置在粘貼html文本時會自動將大寫字母變化成小寫字母,因此angular的某些標籤很容易發生錯誤,因此須要關閉這個自動轉換,方法就是在vs的選項中將文本編輯器中的html高級選項下的粘貼時設置格式設置爲false。
html5內置的數據驗證包括Required、minLength、maxLength、pattern ,咱們能夠將這些標籤應用到咱們的輸入控件上,如
<input type="text" style="width: 300px" class="form-control" required maxlength="10" minLength="4"
[(ngModel)]="myPlanet.id"
ngControl="name"
#planetid="ngForm">
<div [hidden]="planetid.valid || planetid.pristine" class="alert alert-danger">
The id is required !
</div>
這裏的"planetid.valid || planetid.pristine是驗證這個input輸入是否有效,或者數據是否改變。
Formbuilder是咱們能夠採用的另外一種方式來建立Form,這種方式是以模型驅動完成的,更適合咱們進行編碼控制,有利於咱們將邏輯與視圖分離。
Angular2 form 做用機制由兩個主要的組件Controls和Controls group。
Control:包含值和驗證狀態,一個control可以被邦定能夠包含三個可選參數(缺省值,驗證,異步驗證),例如
this.username = new Control('Default value', Validators.required, usernameValidator.checkIfAvailable);
在html應用時使用ngControl標籤綁定這個控件
<input required type=」text」 ngControl=」username」 />
這裏定義的username與input中ngControl指定的名稱要一致。
Control Groups:form定義的一部分,經過將多個cotrol組合在一塊兒造成組。
class App {
name: Control;
username: Control;
email: Control;
form: ControlGroup;
constructor(private builder: FormBuilder) {
this.name = new Control('', Validators.required);
this.email = new Control('', Validators.required);
this.username = new Control('', Validators.required);
this.form = builder.group({
name: this.name,
email: this.email,
username: this.username
});
}
};
html應用時加入ngFormModel來標識。
<form [ngFormModel]=」form」>
除了內置驗證外,咱們還能夠自定義驗證,例子以下
import {Control} from 'angular2/common';
interface ValidationResult
{
[key: string]: boolean;
}
export class UsernameValidator
{
static startsWithNumber( control: Control ): ValidationResult
{
if ( control.value !="" && !isNaN( control.value.charAt( 0 ) ) ){
return { "startsWithNumber": true };
}
return null;
}
}
這個自定義驗證若是輸入的值中首字母是數字則驗證無效,返回null則驗證經過。使用方法
首先import {UsernameValidator} from './customValidate';
而後在咱們須要驗證的控件上加入自定義驗證
this.name = new Control( this.myPlanet.name, UsernameValidator.startsWithNumber );
錯誤提示
<div *ngIf="name.dirty && !name.valid">
<p *ngIf="name.errors.startsWithNumber">
Your name can't start with a number
</p>
</div>
這裏的errors. startsWithNumber就是咱們自定義返回的key值。最好的方式是使用hasError,由於若是返回的startsWithNumber是null的話會引起異常
<p *ngIf="name.hasError('startsWithNumber')">
若是咱們須要使用service去到後臺獲取數據並驗證,則咱們須要使用異步驗證方式,這裏的例子使用promise模擬。
static usernameTaken( control: Control ): Promise<ValidationResult>
{
let q = new Promise(( resolve, reject ) =>
{
setTimeout(() =>
{
if ( control.value !== 'oldkingsir') {
resolve( { "usernameTaken": true});
} else {
resolve( null );
}
}, 1000 )
});
return q;
}
真實應用多是
class ProductValidator {
static productExists(control: Control): {[key: string]: any} {
return new Promise( resolve => {
var productService = new ProductService();
var product: Product;
productService.getProduct(control.value)
.then(productFound => {
if (productFound == null) {
// need to return something if not ok
resolve({productExists: false});
} else {
// need to return null if ok
resolve(null);
}
});
});
}
}
下面須要使用驗證的第三個參數,方式以下
this.name = new Control( this.myPlanet.name,UsernameValidator.startsWithNumber, UsernameValidator.usernameTaken );
html
<div *ngIf="name.dirty && !name.valid">
<span *ngIf="name.pending">Checking istaken...</span>
<p *ngIf="name.hasError('startsWithNumber')">
Your name can't start with a number
</p>
<p *ngIf="name.hasError('usernameTaken')">
Your name is already taken
</p>
</div>
這裏使用了pending來友好提示驗證中。
若是須要進行多個驗證可使用compose組合驗證,以下
this.name = new Control('', Validators.compose([Validators.required, Validators.minLength(4)]));
最後若是整個表單驗證不經過咱們不提交則能夠在提交按鈕上加以處理,如
<button type="submit" class="btn btn-default" [disabled]="!form.valid">Submit</button>