1:在AppModule模塊裏面引入 ReactiveFormsModulecss
要使用響應式表單,就要從@angular/forms包中導入ReactiveFormsModule,並把它添加到你的NgModule的imports數組中。
import { ReactiveFormsModule } from '@angular/forms'; @NgModule({ imports: [ // other imports ... ReactiveFormsModule ], }) export class AppModule { }
2:建立一個新的組件html
ng g c NameEditor
3:請在組件中導入 FormControl 類數組
FormControl類是angular響應式表單最基本的構造快,要註冊單個的表單控件,請在組件中導入FormControl類,並建立一個FormControl的新實例,把它保存在某個屬性裏面。
import { Component } from '@angular/core'; import { FormControl } from '@angular/forms'; @Component({ selector: 'app-name-editor', templateUrl: './name-editor.component.html', styleUrls: ['./name-editor.component.css'] }) export class NameEditorComponent { name = new FormControl(''); }
4:在組件的模板中註冊一個表單控件app
修改模板,爲表單控件添加 formControl 綁定,formControl 是由 ReactiveFormsModule 中的 FormControlDirective 提供的。
<label> Name: <input type="text" [formControl]="name"> </label> <p> Value: {{ name.value }} </p>
使用這種模板綁定語法,把該表單控件註冊給了模板中名爲 name 的輸入元素。這樣,表單控件和 DOM
元素就能夠互相通信了:視圖會反映模型的變化,模型也會反映視圖中的變化。
5:替換表單控件的值異步
FormControl 提供了一個setValue()方法,他會修改這個表單控件的值。
js函數
updateName() { this.name.setValue('Nancy'); }
htmlui
<label> Name: <input type="text" [formControl]="name"> </label> <p> Value:{{name.value}} </p> <p> <button (click)="updateName()">Update Name</button> </p>
在這個例子中,你只使用單個控件FormControl,可是當調用 FormGroup 或 FormArray 的 setValue()
方法時,傳入的值就必須匹配控件組或控件數組的結構才行6:把表單控件分組this
FormControl的實例能控制單個輸入框所對應的控件,FormGroup能夠控制一組FormControl實例的表單狀態,當建立FormGroup時,其中的每個控件都會根據名字進行跟蹤code
1>:建立新的組件component
ng g c ProfileEditor
2>:導入 FormGroup 和 FormControl 類而且建立 FormGroup實例
import { Component } from '@angular/core'; import { FormGroup, FormControl } from '@angular/forms'; @Component({ selector: 'app-profile-editor', templateUrl: './profile-editor.component.html', styleUrls: ['./profile-editor.component.css'] }) export class ProfileEditorComponent { profileForm = new FormGroup({ firstName: new FormControl(''), lastName: new FormControl(''), }); }
如今這些單獨的控件FormControl被收集到了一個控件組中FormGroup, FormGroup 實例擁有和 FormControl 實例相同的屬性(好比 value、untouched)和方法(好比 setValue())。3>:關聯FormGroup的模型和視圖
FormGroup能追蹤每一個單獨控件FormControl的狀態和變化,若是其中某個控件的狀態或值變化了,父控件也會一次新的狀態變動或值變動事件
<form [formGroup]="profileForm"> <label> First Name: <input type="text" formControlName="firstName"> </label> <label> Last Name: <input type="text" formControlName="lastName"> </label> </form>
profileForm經過[formGroup]指令綁定到了 form
元素,在該模型和表單中的輸入框之間建立了一個通信層,FormControlName 指令提供的 formControlName 屬性把每一個輸入框和 FormGroup 中定義的表單控件綁定起來。
4>:關聯FormGroup的模型和視圖
html
<form [formGroup]="profileForm" (ngSubmit)="onSubmit()"> <label> First Name: </label> <input type="text" formControlName="firstName"> <label> Last Name: </label> <input type="text" formControlName="lastName"> <button type="submit" >Submit</button> </form>
js
onSubmit () { console.warn(this.profileForm.value); }
form 標籤所發出的 submit 事件是原生 DOM 事件,經過點擊類型爲 submit 的按鈕能夠觸發本事件
6:嵌套的表單組
js
profileForm = new FormGroup({ firstName: new FormControl(''), lastName: new FormControl(''), address: new FormGroup({ street: new FormControl(''), city: new FormControl(''), state: new FormControl(''), zip: new FormControl('') }) });
html
<form [formGroup]="profileForm" (ngSubmit)="onSubmit()"> <label> First Name: </label> <input type="text" formControlName="firstName"> <label> Last Name: </label> <input type="text" formControlName="lastName"> <div formGroupName="address"> <label>Streel</label> <input type="text" formControlName="street"> <label>City</label> <input type="text" formControlName="city"> <label>State</label> <input type="text" formControlName="state"> <label>Zip Code</label> <input type="text" formControlName="zip"> </div> <button type="submit" [disabled]="!profileForm.valid">Submit</button> </form>
部分模型修改
html
<button (click)="updateProfile()">Update Profile</button>
js
updateProfile() { this.profileForm.patchValue({ firstName: 'Nancy', address: { street: '123 Drew Street' } }); }
patchValue() 方法要針對模型的結構進行更新。patchValue() 只會更新表單模型中所定義的那些屬性。
6:使用 FormBuilder 來生成表單控件
FormBuilder 服務提供了一些便捷方法來生成表單控件。
FormBuilder在幕後也使用一樣的方式來建立和返回這些實例,只是用起來更簡單。 下面會重構 ProfileEditor 組件,用FormBuilder 來代替手工建立這些 FormControl 和 FormGroup。
Step 1 - 導入 FormBuilder 類
import { FormBuilder } from '@angular/forms';
Step 2 - 注入FormBuild 服務
constructor(private fb: FormBuilder) { }
Step 3- 生成表單控件
FormBuilder 服務有三個方法:control()、group() 和 array()。這些方法都是工廠方法,用於在組件類中分別生成
FormControl、FormGroup 和 FormArray。你可使用 group() 方法,用和前面同樣的名字來定義這些屬性。這裏,每一個控件名對應的值都是一個數組,這個數組中的第一項是其初始值。你能夠只使用初始值來定義控件,可是若是你的控件還須要同步或異步驗證器,那就在這個數組中的第二項和第三項提供同步和異步驗證器。
import { Component } from '@angular/core'; import { FormBuilder } from '@angular/forms'; @Component({ selector: 'app-profile-editor', templateUrl: './profile-editor.component.html', styleUrls: ['./profile-editor.component.css'] }) export class ProfileEditorComponent { profileForm = this.fb.group({ firstName: ['張'], lastName: ['娉'], address: this.fb.group({ street: [''], city: [''], state: [''], zip: [''] }), }); constructor(private fb: FormBuilder) { } }
7:簡單的表單驗證
如何把單個驗證器添加到表單控件中,以及如何顯示錶單的總體狀態。
Step 1 - 導入驗證器函數
import { Validators } from '@angular/forms';
響應式表單包含了一組開箱即用的經常使用驗證器函數。這些函數接收一個控件,用以驗證並根據驗證結果返回一個錯誤對象或空值。
Step 2 - 把字段設爲必填
最多見的校驗項是把一個字段設爲必填項。本節描述如何爲 firstName 控件添加「必填項」驗證器。
在組件中,把靜態方法 Validators.required 設置爲 firstName 控件值數組中的第二項。
profileForm = this.fb.group({ firstName: ['', Validators.required], lastName: [''], address: this.fb.group({ street: [''], city: [''], state: [''], zip: [''] }), });
HTML5 有一組內置的屬性,用來進行原生驗證,包括 required、minlength、maxlength等。雖然是可選的,不過你也能夠在表單的輸入元素上把它們添加爲附加屬性來使用它們。這裏咱們把 required 屬性添加到 firstName
輸入元素上。
<input type="text" formControlName="firstName" required>
這些 HTML5 驗證器屬性能夠和 Angular
響應式表單提供的內置驗證器組合使用。組合使用這兩種驗證器實踐,能夠防止在模板檢查完以後表達式再次被修改致使的錯誤。
8:顯示錶單的狀態
如今,你已經往表單控件上添加了一個必填字段,它的初始值是無效的(invalid)。這種無效狀態冒泡到其父 FormGroup 中,也讓這個 FormGroup 的狀態變爲無效的。你能夠經過該 FormGroup 實例的 status 屬性來訪問其當前狀態。
<p> Form Status: {{ profileForm.status }} </p>
9:使用表單數組管理動態控件
FormArray 是 FormGroup 以外的另外一個選擇,用於管理任意數量的匿名控件,若是你事先不知道子控件的數量,FormArray是一個很好的選擇
Step 1 - 導入 FormArray
import { FormArray } from '@angular/forms';
Step 2 - 定義 FormArray
爲 profileForm 添加一個 aliases 屬性,把它定義爲 FormArray 類型。(FormBuilder 服務用於建立 FormArray 實例。)
profileForm = this.fb.group({ firstName: ['張', Validators.required], lastName: ['以'], address: this.fb.group({ street: [''], city: [''], state: [''], zip: [''] }), aliases: this.fb.array([ this.fb.control('') ]) });
Step 3 - 訪問FormArray控件
經過 getter 來訪問控件比較便捷,也容易複用
使用 getter 語法來建立一個名爲 aliases 的類屬性
get aliases() { }
從父控件 FormGroup 中接收綽號的 FormArray 控件。
get aliases() { return this.profileForm.get('aliases') as FormArray; } addAlias() { this.aliases.push(this.fb.control('')); }
Step 3 - 在模板中顯示錶單數組
在模型中定義了 aliases 的 FormArray 以後,你必須把它加入到模板中供用戶輸入,使用 formArrayName 在這個
FormArray 和模板之間創建綁定。
<div formArrayName="aliases"> <h3>Aliases</h3> <button (click)="addAlias()">Add Alias</button> <div *ngFor="let address of aliases.controls; let i=index"> <!-- The repeated alias template --> <label> Alias: <input type="text" [formControlName]="i"> </label> </div> </div>
每當新的 alias 加進來時,FormArray 就會基於這個索引號提供它的控件。這將容許你在每次計算根控件的狀態和值時跟蹤每一個控件。
所有代碼
html
<form [formGroup]="profileForm" (ngSubmit)="onSubmit()"> <label> First Name: </label> <input type="text" formControlName="firstName" required> <label> Last Name: </label> <input type="text" formControlName="lastName"> <div formGroupName="address"> <h3>Address</h3> <label>Streel</label> <input type="text" formControlName="street"> <label>City</label> <input type="text" formControlName="city"> <label>State</label> <input type="text" formControlName="state"> <label>Zip Code</label> <input type="text" formControlName="zip"> </div> <div formArrayName="aliases"> <h3>Aliases</h3> <button (click)="addAlias()">Add Alias</button> <div *ngFor="let address of aliases.controls; let i=index"> <label>Alias</label> <input type="text" [formControlName]="i" > </div> </div> <button type="submit" [disabled]="!profileForm.valid">Submit</button> <p> <button (click)="updateProfile()">Update Profile</button> </p> <p> Form Status: {{ profileForm.status }} </p> </form>
js
import { Component, OnInit } from '@angular/core'; import {FormControl, FormGroup, FormBuilder, Validators, FormArray} from '@angular/forms'; @Component({ selector: 'app-profile-editor', templateUrl: './profile-editor.component.html', styleUrls: ['./profile-editor.component.css'] }) export class ProfileEditorComponent implements OnInit { profileForm = this.fb.group({ firstName: ['張', Validators.required], lastName: ['以'], address: this.fb.group({ street: [''], city: [''], state: [''], zip: [''] }), aliases: this.fb.array([ this.fb.control('') ]) }); constructor(private fb: FormBuilder) { } ngOnInit() { } onSubmit () { console.warn(this.profileForm.value); } updateProfile() { this.profileForm.patchValue({ firstName: 'Nancy', address: { street: '123 Drew Street' } }); } get aliases () { return this.profileForm.get('aliases') as FormArray; } addAlias() { this.aliases.push(this.fb.control('')); } }