小編給大家分享一下Angular2如何實現響應式表單,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!
響應式表單介紹
angular提供了兩種表單搭建技術: 響應式表單和模板驅動式表單。都依賴于@angular/forms庫,并共享了一些通用的表單控件集。
但是他們在原理、代碼風格以及技術上存在區別。他們甚至有自己的模塊:ReactiveFormsModule以及FormsModule。
響應式表單(ReactiveFormsModule):
anguar的響應式表單簡化了管理數據時響應式風格的編碼實現,使用了在無視圖數據模型(從服務器獲取)以及以視圖為導向的模型用于保持屏幕上HTML控件顯示的值與狀態。響應式表單提供了響應式模式測試以及驗證上的便利。
使用響應式表單,你將在組件類中創建一個anular的表單控件樹對象,并在組件模板中使用提供的技術綁定到原生表單控件標簽中。
你直接在組件類中創建并操作控件對象。因為組件類能直接訪問到數據模型以及表單控件結構,你可以將數據模型值推送到表單控件以及將用戶的更改響應到后邊來。組件可以觀察表單控件狀態的更改并響應這些更改。
直接使用表單控件對象工作的一個好處是值以及驗證的更新總能夠同步完成并受你控制。你不會遇到有時候因為模板驅動表單造成的時間問題,并且響應式表單更易測試。
為了保持響應的一致性,組件會保存不一致的數據模型,將其視為純粹的原始值。不會直接更新數據模型,組件會提取用戶的更改并轉發到外面的組件或服務中,(可能是用來保存他們的)并返回一個新數據模型到組件,用于響應模型狀態的更新。
使用響應式表單指令不需要你依賴于全部響應式原理,但是這確實能促進響應式編程方法如果你選擇了要使用這個方法的話。
模板驅動式表單(FormsModule):
模板驅動式的表單使用了完全不同的方式。
你在組件模板中放置HTML表單控件(input這些)并使用比如ngModel這些指令綁定到數據模型屬性。
你不需要創建angular表單控件對象,因為angular會根據你的數據綁定信息自動幫你創建出來。你不是推送或者拉取數據值。angular在ngModel中幫你處理了。angular會更新那些被改變的數據值。
出于這個原因,ngModel不再是ReactiveFormsModule的一部分了。
這意味著可以在組件類中寫更少的代碼,不過模板驅動表單是異步工作的,這可能會在某些情況下復雜化開發。
同步vs異步
響應式表單是同步的。模板驅動表單是異步的,這是其區別的根源。
在響應式表單中,你在代碼中創建一個完整的表單控件樹。你可以從子表單或父表單中立即更新或取回一個值,因為所有的控件都可訪問到。
模板驅動表單將他們的表單控件的創建委托給了指令。為了避免“檢查后又更改”的錯誤,這些指令使用了不止一個循環來建立整個控件樹。這意味著你必須在操作任何組件類中的空間表單時等那么一小會兒。
比如說,如果你使用@ViewChild(NgForm)查詢注入到表單控件中并在ngAfterViewInit這個生命周期鉤子中檢查它,你將發現它沒有子元素。你必須等一會,使用setTimeout來等待,然后你才能從這個空間中去除值并驗證它或者將它設置為新的值。
模板驅動表單的異步性同時復雜化了單元測試。你必須使用async()或者fakeAsync()來包裝你的測試塊來避免找不到表單的值。而如果使用的是響應式表單,一切都如你所愿的存在著。
哪一個方式更好?
沒有哪種是更好的。他們是兩種不同的搭建方式,各自擁有長處和短處。使用最適合你的方式才是對的。在一個應用中你可能兩種方式都要使用到。
本文僅僅會描述響應式的范例與精華所在。對于模板驅動式表單,可以前往表單介紹頁。
接下來你將寫出你自己的項目來演示響應式表單。然后你將學會關于angular表單類以及如何在響應式表單中使用它。
對上文的總結就是,相比ng1中數據的雙向綁定,ng2保留了這個雙向綁定能力(底層其實優化了很多),原先的ng-model指令升級成了ngModel,使用的功能保持不變。
同時盡管ng2版本的數據雙向綁定得到了很大的優化,仍改變不了其數據異步綁定的方式,因為ng2不能確定數據何時綁定,我們也不能確定很多網絡請求得到的數據到來的時間。
在ng1中其實這個機制會有一些尷尬的場景,至少筆者在一些情況下不得不在一些業務場景下使用setTimeout來保證數據已經成功綁定進入scope的watch循環,但這個異步綁定數據又是不可避免的,除非我們自己來適應實際項目改寫angular代碼了。
所以ng2就提供了讓我們配合具體項目場景改寫ngModel的能力,也就是原文介紹的響應式表單。
其跟ngModel的關系就是,ngModel是響應式表單的官方實現,其在我們綁定數據時自動為我們實現響應式表單中用到的幾個機制,如果我們需要數據嚴格的實時同步綁定,就不必使用ngModel,可以親自來編寫響應式的表單,步驟覆蓋了組件模板到數據模型類整條龍,而這么多事情在合適的場景下使用ngModel已經可以實現了,這兩種表單綁定的方式各有其優勢。
1. 使用響應式表單
響應式表單的能力封裝在ReactiveFormsModule中,并且跟FormsModule同時包含在@angular/forms這個包中。
表單類的要點:
1.AbstractControl是FormControl、FormGroup、FormArray這三個實例表單類的抽象基類。它提供了他們的通用行為以及屬性,其中就有observable。
2.FormControl在單個表單控件中檢查值并驗證狀態。它負責將其通知給HTML表單控件(比如input這些)。
3.FormGroup負責AbstractControl實例的一個組的值與驗證狀態。組的屬性包含了它們的子控件。你的組件的頂級表單就是一個FormGroup。
4.FormArray負責AbstractControl實例的數值索引數組的值與狀態驗證。
2. FormControl
最核心的指令就是FormControl,算是底層的ngModel,在模板標簽中跟定義好的數據模型字段綁定起來,就像這樣:
<h3>Hero Detail</h3> <h4><i>Just a FormControl</i></h4> <label class="center-block">Name: <input class="form-control" [formControl]="name"> </label>
同時在組件代碼中需要將上例中這個name字段聲明為FormControl類:
export class HeroDetailComponent1 { name = new FormControl(); }
3. FormGroup
將多個FormControl對象分組到FormGroup中,用來方便管理。定義方法如下:
import { Component } from '@angular/core'; import { FormControl, FormGroup } from '@angular/forms'; export class HeroDetailComponent2 { heroForm = new FormGroup ({ name: new FormControl() }); }
此時模板標簽中也要分組來寫:
<h3>Hero Detail</h3> <h4><i>FormControl in a FormGroup</i></h4> <form [formGroup]="heroForm" novalidate> <div class="form-group"> <label class="center-block">Name: <input class="form-control" formControlName="name"> </label> </div> </form>
現在的效果就是可以從heroForm中實時讀取到其值和一些附加的狀態的變化。
可以在模板中添加兩個標簽來展示數據的更改:
<p>Form value: {{ heroForm.value | json }}</p> <p>Form status: {{ heroForm.status | json }}</p>
4. FormBuilder
還有個新概念就是FormBuilder,是用來幫助創建表單類的:
1. 顯示聲明heroForm屬性的類型為FormGroup,后面你將會初始化它
2. 注入FormBuilder到構造器中
3. 使用FormsBuilder添加新方法定義heroForm,叫做createForm。
4. 在構造器中執行createForm方法。
export class HeroDetailComponent3 { heroForm: FormGroup; // <--- heroForm is of type FormGroup constructor(private fb: FormBuilder) { // <--- inject FormBuilder this.createForm(); } createForm() { this.heroForm = this.fb.group({ name: '', // <--- the FormControl called "name" }); } }
上例中執行createForm方法即可動態快速的創建出表單類,其在一些表單類需要更改的場景下可以使用。
5. setValue和patchValue
這兩個方法是真正給表單模型賦值用的。因為表單顯示的數據與真實的底層數據肯定不能使同一個,否則表單輸入數據一旦更改,源數據就被污染了,而這兩個方法就是用來將源數據賦值到表單模型數據上的。
每當需要賦值時就可以調用,其中setValue必須準確賦值,并且會在數據不匹配時報告錯誤;而patchValue沒有這么嚴格,但可以傳一個對象,且不匹配時不會報告錯誤。
而我們要做的就是在ng2組件的ngOnChanges回調中手動執行setValue設置數據值。比如這樣:
ngOnChanges() this.heroForm.setValue({ name: this.hero.name, address: this.hero.addresses[0] || new Address() }); }
同時ng2還提供了一個reset方法來重新調用setValue方法(setValue本身好像只是用來一次性賦值的)。
6. FormArray
FormArray是用來對付FormGroups列表的,比如一個英雄有可能有多個address字段,address字段本身就是個FormGroup,此時就要用到FormArray了:
this.heroForm = this.fb.group({ name: ['', Validators.required ], secretLairs: this.fb.array([]), // <-- secretLairs as an empty FormArray power: '', sidekick: '' });
獲取FormArray要用到FormGroup提供的一個get方法:
get secretLairs(): FormArray { return this.heroForm.get('secretLairs') as FormArray; };
其顯示的模板如下:
<div formArrayName="secretLairs" class="well well-lg"> <div *ngFor="let address of secretLairs.controls; let i=index" [formGroupName]="i" > <!-- The repeated address template --> </div> </div>
以上是“Angular2如何實現響應式表單”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業資訊頻道!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。