表單多是WEB世界里最重要的,通過表單獲得用戶的輸入.另外一方面,表單看起來又是簡單的,你放置1個input標簽,1個submit按鈕,然后點擊按鈕,提交,有甚么難的呢?
實踐證明,表單確切是很復雜的,理由以下:
- 表單輸入意味著修改服務器與客戶真?zhèn)€數(shù)據(jù).
- 改變通常會需要去反應到其他的地方
- 用戶會隨便輸入不同的值,所以需要校驗
- 如果需要,需要清楚地標明毛病
- 依賴字段具有復雜的邏輯
- 不依托DOM選擇器,我們不能測試表單
榮幸的是,angular2提供了解決這些問題的工具:
- Controls封裝了輸入,并且提供1個與它們工作的對象
- Validators給了我們1個校驗工具
- Observers讓我們可以檢測我們的表單,并且根據(jù)需要作出反應
在這1章,我們會深入學習表單.
ng2中,表單的兩個基礎(chǔ)設(shè)施就是Controls 和 Control Groups
Controls代表1個簡單的輸入域,它是ng2中表單的最小單元.
Controls封裝了字段的值和有效,修改,毛病的狀態(tài).
比如,我們會在Typescript中像下面1樣使用Control
// create a new Control with the value "Nate"
let nameControl = new Control("Nate");
let name = nameControl.value; // -> Nate
// now we can query this control for certain values:
nameControl.errors // -> StringMap<string, any> of errors
nameControl.dirty // -> false
nameControl.valid // -> true
// etc.
為了構(gòu)建表單,我們創(chuàng)建Control或Control group,然后添加元數(shù)據(jù)和邏輯給它們.
像angular中的其他事情1樣,我們有1個類(在本例子中是Control),我們會作為屬性添加給DOM(本例子中是ngControl),以下:
<!-- part of some bigger form -->
<input type="text" ngControl="name" />
在我們的表單上下文中新建1個Control對象.
許多表單都不止1個值,所以我們需要管理很多Controls,如果我們希望去校驗我們的表單,去迭代每個Control并校驗是笨重的.為了解決這個問題,ControlGroup提供了1個封裝.
下面我們創(chuàng)建1個ControlGroup.
let personInfo = new ControlGroup({
firstName: new Control("Nate"),
lastName: new Control("Murray"),
zip: new Control("90210")
})
ControlGroup和Control有1個公共的父類(AbstractControl).也就是說我們可以像1個簡單Control1樣檢查personInfo的值和狀態(tài).
personInfo.value; // -> {
// firstName: "Nate",
// lastName: "Murray",
// zip: "90210"
//}
// now we can query this control group for certain values, which have sensible
// values depending on the children Control's values:
personInfo.errors // -> StringMap<string, any> of errors
personInfo.dirty // -> false
personInfo.valid // -> true
// etc.
注意,當我們獲得ControlGroup的值時,我們會獲得到1個key-value的對象.
這里有許多創(chuàng)建表單的重要方面我們沒有提及,下面我們來逐1學習.
下面這個是我們將要創(chuàng)建的1個簡單的表單:
在我們的理解中,我們創(chuàng)建1個電子商務型的網(wǎng)站,我們會列出我們出售的產(chǎn)品列表.在這個例子中,我們需要存儲產(chǎn)品的SKU碼,因此,我們創(chuàng)建1個獲得SKU碼的簡單表單,它僅僅只有1個輸入域.
我們的表單是非常簡單的,它只有1個input和1個sumbit按鈕.
讓我們將這個表單組裝成1個組件,如果你沒有忘記,創(chuàng)建組件的3個部份為:
- 配置
- 創(chuàng)建模板
- 實現(xiàn)組件類
code/forms/app/forms/demo_form_sku.ts
import { Component } from '@angular/core';
import { FORM_DIRECTIVES } from '@angular/common';
@Component({
selector: 'demo-form-sku',
directives: [FORM_DIRECTIVES],
注意,這里我們導入了FORM_DIRECTIVES,FORM_DIRECTIVES是1個指令組,它包括:
- ngControl
- ngControlGroup
- ngForm
- ngModel
- …
我們沒有怎樣使用這些指令,也沒有說明它們能做甚么.但是,現(xiàn)在,只需要知道我們需要使用這些指令就能夠了.
code/forms/app/ts/forms/demo_form_sku.ts
<div class="ui raised segment">
<h2 class="ui header">Demo Form: Sku</h2>
<form #f="ngForm" (ngSubmit)="onSubmit(f.value)" class="ui form">
<div class="field">
Forms in Angular 2 127
<label for="skuInput">SKU</label>
<input type="text" id="skuInput" placeholder="SKU" ngControl="sku">
<button type="submit" class="ui button">Submit</button>
</div>
</form>
</div>
注意,我們導入了FORM_DIRECTIVES,所以我們可使用ngForm添加到form上面.
NgForm做的事情是有好多好處的,而且也不明顯.
導入FORM_DIRECTIVES后,ngForm會自動隱士地添加到任何的form標簽上面.
ngForm給了我們兩個東西:
- 1個命名為ngForm的ControlGroup
- 1個ngSubmit的輸出
你可以在我們的代碼中看到,我們使用了這兩個東西:
<form #f="ngForm" (ngSubmit)="onSubmit(f.value)" class="ui form">
</form>
首先我們使用#f=”ngForm”創(chuàng)建了名為ngForm的表單,#v=thing說明,我們希望使用本地變量v代表這個view.
這里,我們創(chuàng)建了ngForm的標明,并綁定到變量f上.
我們的ngForm指令從哪里來? 它來自于NgForm指令.
ngForm的類型是甚么?它是ControlGroup.這意味著我們可以將我們的視圖作為ControlGroup使用.(ngSubmit)代表的是我們提交的時候需要做的事情.
所有添加起來的理解就是,當我們提交表單的時候,傳遞ControlGroup的value作為參數(shù),調(diào)用我們組建的onSubmit方法.
在我們討論ngControl前,input標簽有1些事情是我們感興趣的.
code/forms/app/ts/forms/demo_form_sku.ts
<form #f="ngForm" (ngSubmit)="onSubmit(f.value)" class="ui form">
<div class="field">
Forms in Angular 2 127
<label for="skuInput">SKU</label>
<input type="text" id="skuInput" placeholder="SKU" ngControl="sku">
<button type="submit" class="ui button">Submit</button>
</div>
</form>
- class=”ui form”是可選的
- for屬性與input的id是對應的
- placeholder是當用戶沒有輸入的時候用來提示用的.
NgControl指令是用來標識ngControl這個選擇器.這就意味著我們的input標簽添加了這個屬性:ngControl=”whatever”,這個例子中是sku.
NgControl會自動創(chuàng)建1個Control添加給父組件,這個例子中是ControlGroup.然后綁定這個DOM元素給Control.也就是說,我們通過名字sku將input與Control進行關(guān)聯(lián).
code/forms/app/ts/forms/demo_form_sku.ts
export class DemoFormSku { onSubmit(form: any): void {
console.log('you submitted value:', form);
}
}
將所有代碼合起來,像下面這樣:
code/forms/app/ts/forms/demo_form_sku.ts
import { Component } from '@angular/core';
import { FORM_DIRECTIVES } from '@angular/common';
@Component({
selector: 'demo-form-sku',
directives: [FORM_DIRECTIVES],
template: `
<div class="ui raised segment">
<h2 class="ui header">Demo Form: Sku</h2>
<form #f="ngForm"
(ngSubmit)="onSubmit(f.value)"
class="ui form">
<div class="field">
<label for="skuInput">SKU</label>
<input type="text"
id="skuInput"
placeholder="SKU"
ngControl="sku">
</div>
<button type="submit" class="ui button">Submit</button>
</form>
</div>
`
})
export class DemoFormSku {
onSubmit(form: any): void {
console.log('you submitted value:', form);
}
}
如果你運行這個程序,閱讀器中會顯示下面這樣:
隱式使用ngForm和ngControl是方便的,但是它沒有給予我們太多的可自定義選項,通常,我們會使用1個更加復雜的方式創(chuàng)建form,那就是FormBuilder.
FormBuilder是1個幫助類,幫助我們創(chuàng)建表單.你可以將其理解為工廠方法.
讓我們將FormBuilder添加到我們前面的例子中,看下面:
- 在我們組件定義類中怎樣使用FormBuilder
- 是view中怎樣使用自定義的ControlGroup.
在我們的組件類構(gòu)造器參數(shù)中注入1個參數(shù).
code/forms/app/ts/forms/demo_form_sku_with_builder.ts
export class DemoFormSkuBuilder { myForm: ControlGroup;
constructor(fb: FormBuilder) {
this.myForm = fb.group({
'sku': ['ABC123'] });
}
onSubmit(value: string): void {
console.log('you submitted value: ', value);
}
注入以后,1個FormBuilder的實例將會被創(chuàng)建,并且我們將其分配給局部變量fb.
我們將會使用FormBuilder的兩個主要方法:
- control:創(chuàng)建1個新的Control
- group: 創(chuàng)建1個新的ControlGroup
注意,我們在本例子中使用myForm局部變量代表我們的表單.
myForm的類型是ControlGroup.通過fb.group創(chuàng)建的.group的參數(shù)是1個key-value,它代表這個ControlGroup里面的Control.在這個例子中,我們設(shè)置了1個名字為sku的Control,它的值是ABC123.
現(xiàn)在,我們有1個myForm的ControlGroup,我們需要使用它(通過綁定它到我們的form元素).
我們希望改變?nèi)ナ褂梦覀兊膍yForm.如果沒有忘記,在上面,我們說,導入FORM_DIRECTIVES時,ngForm會自動利用到我們的form元素上.我們也注意到了,ngForm創(chuàng)建了它自己的ControlGroup.好了,在這個例子中,我們不希望使用外部的ControlGroup,我們希望使用我們自己定義的myForm.我們應當怎樣做?
當我們需要使用我們自己的ControlGroup時,angular提供了另外1種方式:它叫著ngFormModel,并且我們可以像下面這樣使用它:
code/forms/app/ts/forms/demo_form_sku_with_builder.ts
<form [ngFormModel]="myForm"
(ngSubmit)="onSubmit(myForm.value)"
這里,我們使用ngFormModel告知angular,我們將會使用myForm到這個上.
我們需要使用myForm的onSubmit代替f的onSubmit,最后1件事情就是綁定我們的Control到input上,使用NgFormControl.
code/forms/app/ts/forms/demo_form_sku_with_builder.ts
<input
type="text"
id="skuInput"
placeholder="SKU"
[ngFormControl]="myForm.controls['sku']">
所有代碼:
code/forms/app/ts/forms/demo_form_sku_with_builder.ts
import { Component } from '@angular/core';
import {
FORM_DIRECTIVES,
FormBuilder,
ControlGroup
} from '@angular/common';
@Component({
selector: 'demo-form-sku-builder',
directives: [FORM_DIRECTIVES],
template: `
<div class="ui raised segment">
<h2 class="ui header">Demo Form: Sku with Builder</h2>
<form [ngFormModel]="myForm"
(ngSubmit)="onSubmit(myForm.value)"
class="ui form">
<div class="field">
<label for="skuInput">SKU</label>
<input type="text"
id="skuInput"
placeholder="SKU"
[ngFormControl]="myForm.controls['sku']">
</div>
<button type="submit" class="ui button">Submit</button>
</form>
</div>
`
})
export class DemoFormSkuBuilder {
myForm: ControlGroup;
constructor(fb: FormBuilder) {
this.myForm = fb.group({
'sku': ['ABC123']
});
}
onSubmit(value: string): void {
console.log('you submitted value: ', value);
}
}
記住:
隱式創(chuàng)建ControlGroup和Control使用:
- ngForm
- ngControl
綁定存在的ControlGroup和Control使用:
- ngFormModel
- ngFormControl
用戶常常不會按正確的模式輸入正確的數(shù)據(jù),如果用戶沒有按正確的格式輸入數(shù)據(jù),我們可以給用戶1個反饋,并且讓其不能提交,這類情況下,我們使用校驗器(Validators).
Validators被Validators模塊提供,而且,最簡單的Validators是Validators.required.
Validators.require標明該Control是必填字段.
為了使用Validators,我們必須做兩件事情.
- 分配1個Validator給Control
- 檢查Validator狀態(tài),并給出反饋
let control = new Control('sku', Validators.required);
在我們的例子中,由于使用了FormBuilder,所以可以像下面這樣:
code/forms/app/ts/forms/demo_form_with_validations_explicit.ts
constructor(fb: FormBuilder) {
this.myForm = fb.group({
'sku': ['', Validators.required]
現(xiàn)在,我們需要使用Validators到我們的view上,在View上,有兩種方式訪問Validators.
- 我們可以明確分配1個Control sku到我們類的實例,這個是比較啰嗦的,但是更加靈活.
- 在view中,我們從myForm獲得Control sku,這中方式,在Component類中的代碼量少,但是在view中的代碼多.
為了分析他們的區(qū)分,我們看下面的例子.
以下:
更加靈活的方式是將Controls分開成單獨的Control放在組件類中,下面是我們的類代碼:
code/forms/app/ts/forms/demo_form_with_validations_explicit.ts
export class DemoFormWithValidationsExplicit {
myForm: ControlGroup;
sku: AbstractControl;
constructor(fb: FormBuilder) {
this.myForm = fb.group({
'sku': ['', Validators.required]
});
this.sku = this.myForm.controls['sku'];
}
onSubmit(value: string): void {
console.log('you submitted value: ', value);
}
}
注意:
- 我們在類中定義sku: AbstractControl
- 當使用FormBuilder創(chuàng)建以后,我們分配給sku.
這是1個很好的注意,它表明我們可以在我們的view的任何地方使用sku.現(xiàn)在,我們的sku是可以被validated.我們希望找到不同的方式去使用它.
- 校驗所有的form,提供1條信息
- 分開校驗每個Control,并提供1條信息
- 分開校驗每個Control,當不合法的時候使用紅色標注
- 分開校驗每個Control,是不是已輸入,如果沒有輸入,顯示1條信息
我們可以通過檢查myForm.valid來校驗myForm.
code/forms/app/ts/forms/demo_form_with_validations_explicit.ts
<div *ngIf="!myForm.valid"
我們也能夠在字段不符合規(guī)定的時候顯示1條信息
code/forms/app/ts/forms/demo_form_with_validations_explicit.ts
[ngFormControl]="sku">
<div *ngIf="!sku.valid"
我們也能夠標注字段的色彩,當不合法的時候.
code/forms/app/ts/forms/demo_form_with_validations_explicit.ts
<div class="field"
[class.error]="!sku.valid && sku.touched">
當需要依托特定的校驗器時,也能夠制定.通過hasError()來實現(xiàn).
code/forms/app/ts/forms/demo_form_with_validations_explicit.ts
class="ui error message">SKU is invalid</div>
<div *ngIf="sku.hasError('required')"
code/forms/app/ts/forms/demo_form_with_validations_explicit.ts
/* tslint:disable:no-string-literal */
import { Component } from '@angular/core';
import {
CORE_DIRECTIVES,
FORM_DIRECTIVES,
FormBuilder,
ControlGroup,
Validators,
AbstractControl
} from '@angular/common';
@Component({
selector: 'demo-form-with-validations-explicit',
directives: [CORE_DIRECTIVES, FORM_DIRECTIVES],
template: `
<div class="ui raised segment">
<h2 class="ui header">Demo Form: with validations (explicit)</h2>
<form [ngFormModel]="myForm"
(ngSubmit)="onSubmit(myForm.value)"
class="ui form">
<div class="field"
[class.error]="!sku.valid && sku.touched">
<label for="skuInput">SKU</label>
<input type="text"
id="skuInput"
placeholder="SKU"
[ngFormControl]="sku">
<div *ngIf="!sku.valid"
class="ui error message">SKU is invalid</div>
<div *ngIf="sku.hasError('required')"
class="ui error message">SKU is required</div>
</div>
<div *ngIf="!myForm.valid"
class="ui error message">Form is invalid</div>
<button type="submit" class="ui button">Submit</button>
</form>
</div>
`
})
export class DemoFormWithValidationsExplicit {
myForm: ControlGroup;
sku: AbstractControl;
constructor(fb: FormBuilder) {
this.myForm = fb.group({
'sku': ['', Validators.required]
});
this.sku = this.myForm.controls['sku'];
}
onSubmit(value: string): void {
console.log('you submitted value: ', value);
}
}
像我們上面1樣,我們在組件類中創(chuàng)建了1個實例變量存儲每個input標簽.
但是我們能不能不創(chuàng)建實例變量而直接閱讀Control呢?答案是肯定的.我們會學習閱讀Form的其他方式.
讓我們看看另外的例子.
code/forms/app/ts/forms/demo_form_with_validations_shorthand.ts
export class DemoFormWithValidationsShorthand {
myForm: ControlGroup;
constructor(fb: FormBuilder) {
this.myForm = fb.group({
'sku': ['', Validators.required] });
}
onSubmit(value: any): void {
console.log('you submitted value:', value.sku);
}
}
這兩個例子的代碼有點像,但是仔細看,你會發(fā)現(xiàn),sku: AbstractControl已不在這里面了.
讓我們看看這3個字段級別的校驗器,跟上面的作為對照.
由于我們沒有直接定義1個本地變量保存sku援用,所以我們需要1種取得它援用的方式,這里有兩種方式:
- 通過myForm.find
- 通過ngFormControl
myForm具有1個find函數(shù),它可以通過路徑找到它的子元素,然后校驗他們.
code/forms/app/ts/forms/demo_form_with_validations_shorthand.ts
<div class="field"
[class.error]="!myForm.find('sku').valid && myForm.find('sku').touched">
這比前面的代碼還多,不可取.
這里有另外1種方式取得援用,**通過ngForm導出ngFormControl.這是前面章節(jié)沒有講過的內(nèi)容.
Component可以導出他們自己的援用,讓你可以在視圖中援用它們
我們在接下來的章節(jié)中講授怎樣使用exportAs導出,但是現(xiàn)在只需要知道,很多內(nèi)建組件都可以像這樣做.
在這個例子中,NgFormControl導出它自己作為ngForm.你可使用#reference來援用他們.
以下:
code/forms/app/ts/forms/demo_form_with_validations_shorthand.ts
<input
type="text"
id="skuInput"
placeholder="SKU"
#sku="ngForm"
[ngFormControl]="myForm.controls['sku']">
注意,上面的就是使用ngFormControl導出它自己引入變量sku,但是要注意,sku是1個指令,不是Control.為了訪問sku Control,需要使用sku.control.
現(xiàn)在,sku對我們來講是可以利用的.我們可以像下面這樣使用它.
code/forms/app/ts/forms/demo_form_with_validations_shorthand.ts
<div *ngIf="!sku.control.valid"
class="ui error message">SKU is invalid</div>
<div *ngIf="sku.control.hasError('required')" class="ui error message">SKU is required</div>
當我們創(chuàng)建1個援用的時候,它是可以在其兄弟節(jié)點或子節(jié)點使用,但是不能在其父節(jié)點使用.
比如,不能像下面這樣:
// this won't work
<div class="field"
[class.error]="!sku.control.valid && sku.control.touched">
由于div是form的父元素.
code/forms/app/ts/forms/demo_form_with_validations_shorthand.ts
import { Component } from '@angular/core';
import {
CORE_DIRECTIVES,
FORM_DIRECTIVES,
FormBuilder,
ControlGroup,
Validators
} from '@angular/common';
@Component({
selector: 'demo-form-with-validations-shorthand',
directives: [CORE_DIRECTIVES, FORM_DIRECTIVES],
template: `
<div class="ui raised segment">
<h2 class="ui header">Demo Form: with validations (shorthand)</h2>
<form [ngFormModel]="myForm"
(ngSubmit)="onSubmit(myForm.value)"
class="ui form">
<div class="field"
[class.error]="!myForm.find('sku').valid && myForm.find('sku').touched">
<label for="skuInput">SKU</label>
<input type="text"
id="skuInput"
placeholder="SKU"
#sku="ngForm"
[ngFormControl]="myForm.controls['sku']">
<div *ngIf="!sku.control.valid"
class="ui error message">SKU is invalid</div>
<div *ngIf="sku.control.hasError('required')"
class="ui error message">SKU is required</div>
</div>
<div *ngIf="!myForm.valid"
class="ui error message">Form is invalid</div>
<button type="submit" class="ui button">Submit</button>
</form>
</div>
`
})
export class DemoFormWithValidationsShorthand {
myForm: ControlGroup;
constructor(fb: FormBuilder) {
this.myForm = fb.group({
'sku': ['', Validators.required]
});
}
onSubmit(value: any): void {
console.log('you submitted value:', value.sku);
}
}
我們通常需要編寫自己的校驗器,怎樣做?
為了弄清楚怎樣實現(xiàn)自定義校驗器,讓我們看看內(nèi)建的Validators.required.
export class Validators {
static required(c: Control): StringMap<string, boolean> {
return isBlank(c.value) || c.value == "" ? {"required": true} : null;
}
輸入為1個Control,輸出為1個
比如我們希望標志我們的sku,輸入的必須是以123開頭的.
我可以像下面這樣寫:
code/forms/app/ts/forms/demo_form_with_custom_validations.ts
function skuValidator(control: Control): { [s: string]: boolean } { if (!control.value.match(/^123/)) {
return {invalidSku: true};
}
}
當輸入的不是以123開頭時,這個校驗器會返回invalidSku的毛病代碼.
現(xiàn)在我們需要將skuValidator添加到Control上面去.但是這里有1個問題,我們的sku上面已有1個校驗器了,我們怎樣添加多個校驗器到同1個Control呢?
答案是我們使用Validators.compose.以下:
code/forms/app/ts/forms/demo_form_with_custom_validations.ts
this.myForm = fb.group({
'sku': ['', Validators.compose([
Validators.required, skuValidator])]
});
Validators.compose包裝多個校驗器給Control,當所有的校驗器都是有效的時候,Control才是有效的.否則校驗不通過.
現(xiàn)在我們可以在視圖中使用這個新的校驗器.
code/forms/app/ts/forms/demo_form_with_custom_validations.ts
<div *ngIf="sku.hasError('invalidSku')"
class="ui error message">SKU must begin with <tt>123</tt></div>
到現(xiàn)在為止,當表單提交的時候,我們只是從我們的表單中讀取數(shù)據(jù).但是通常,我們希望監(jiān)聽每個Control的變化.
ControlGroup與Control都有1個EventEmitter,它可以用來監(jiān)聽數(shù)據(jù)的變化.
為了監(jiān)聽變化,我們需要做下面的兩個操作:
- 通過調(diào)用control.valueChanges獲得
- 使用EventEmitter.observer方法添加1個視察者
下面是1個例子:
code/forms/app/ts/forms/demo_form_with_events.ts
export class DemoFormWithEvents {
myForm: ControlGroup;
sku: AbstractControl;
constructor(fb: FormBuilder) {
this.myForm = fb.group({
'sku': ['', Validators.required]
});
this.sku = this.myForm.controls['sku'];
this.sku.valueChanges.subscribe(
(value: string) => {
console.log('sku changed to:', value);
}
);
this.myForm.valueChanges.subscribe(
(form: any) => {
console.log('form changed to:', form);
}
);
}
onSubmit(form: any): void {
console.log('you submitted value:', form.sku);
}
}
這里我們監(jiān)聽兩個事件:sku變化事件和全部form的變化事件.
我們傳遞進去的是1個簡單的key.接下來是1個函數(shù),當值變哈的時候會被調(diào)用.
ngModel是1個特殊的指令,它綁定1個Model給form.ngModel是1個實現(xiàn)了雙向數(shù)據(jù)綁定的特殊指令.雙向數(shù)據(jù)綁定是比較復雜的.angular2默許使用的是單項數(shù)據(jù)流,但是在Form中,由于需要跟蹤用戶改變,所以使用雙向數(shù)據(jù)綁定.
看下面的例子:
code/forms/app/ts/forms/demo_form_ng_model.ts
export class DemoFormNgModel {
myForm: ControlGroup; productName: string;
constructor(fb: FormBuilder) {
this.myForm = fb.group({
'productName': ['', Validators.required] });
}
onSubmit(value: string): void {
console.log('you submitted value: ', value);
}
}
注意,我們在勒種定義了productName: string 實例變量.然后讓我們看看在input標簽中怎樣使用ngModel:
code/forms/app/ts/forms/demo_form_ng_model.ts
<input
type="text"
id="productNameInput"
placeholder="Product Name"
[ngFormControl]="myForm.find('productName')"
[(ngModel)]="productName">
ngModel的語法是很奇特的,它使用[]和()合起來,由前面的可知,[]是輸入,()是輸出,也就是說雙向就是輸入和輸出都綁定了.
然后,我們將productName顯示出來.
code/forms/app/ts/forms/demo_form_ng_model.ts
<div class="ui info message">
The product name is: {{productName}}
</div>
看起來像下面這樣:
可以看到,是實時同步的.
Form有很多的復雜功能,但是angular2提供了1個清晰明了的方式,1旦你學會使用了ControlGroups, Controls, 和 Validations,使用表單就會變得很簡單了.
上一篇 給你一臺美國電視......
下一篇 Git學習筆記整理