# 多奇 2020 年 2 月新人職前培訓班 - 4 ###### tags: `Training` `Course` ### Template Driven Form 練習 請至此 [連結](https://github.com/changda0616/doggy-training-template-driven-form),閱讀 `READMD` 需求完成練習 --- ## 介紹 ### Model-driven Form 1. 又稱 Reactive Forms 2. 三大組成要素 1. `FormGroup` 2. `FormControl` 3. `FormArray` -> 適用動態新增的欄位 3. 不再使用 `ngModel`, 不再需要 `name` 屬性 ### Reactive Forms 中的重要類別 - AbstractControl - 為 Reactive Forms 架構中三個表單類別共同的抽象基底類別(abstract bass class) - FormControl - 追蹤某一個表單控制項的欄位值與驗證狀態 - FormGroup - 追蹤一群表單控制項的欄位值與驗證狀態 - 以「物件」的方式進行群組 ( 欄位之間沒有順序性,索引值為字串 ) - FormArray - 追蹤一群表單控制項的欄位值與驗證狀態 - 追蹤一群表單控制項的欄位值與驗證狀態 - 該群組會以「陣列」的方式進行群組 ( 欄位之間的索引值為數值 ) ![](https://i.imgur.com/EMo8Meg.png) ## [實作](https://github.com/changda0616/doggy-training-reactive-form) ### 表單建立方式(2 種) 1. 使用 FormBuilder (較為簡潔) 2. 直接使用 FormControl, FormGroup, FormArray 建立表單元件 #### FormBuilder ```javascript=1 this.form = this.fb.group({ step1: this.fb.group({ name: ['', Validators.required], phone: ['', [Validators.required, Validators.minLength(7)]] }), step2: this.fb.group({ recommandationNumber: ['', Validators.required], recommandation: [{ value: '', disabled: true }, Validators.required] }) }); ``` #### 直接使用 FormControl, FormGroup, FormArray ```javascript=1 this.form = new FormGroup({ step1: new FormGroup({ name: new FormControl(['', Validators.required]), phone: new FormControl('', [Validators.required, Validators.minLength(7)]) }), step2: new FormGroup({ recommandationNumber: new FormControl(['', Validators.required]), recommandation: new FormControl([{ value: '', disabled: true }, Validators.required]) }) }); ``` ### 更新表單內容(3 種) - setValue vs patchValue vs reset #### setValue - 傳入的資料結構需與 FormGroup 中的物件相同, 屬性找不到會出錯 ```javascript=1 this.step1.setValue({ name: '', phone: '' }); ``` #### patchValue - 僅更新部分屬性,若傳入找不到的屬性,自動忽略 ```javascript=1 this.step1.patchValue({ name: '', mobile: '' }); ``` #### reset - 重置表單內容 1. 清空表單狀態 - 轉為 pristine, untouched 2. 清空欄位內容 - 欄位值變成 null ```javascript=1 this.form.reset(); ``` 3. 重置為預設內容,若傳入找不到的屬性,自動忽略 ```javascript=1 this.form.reset({ step1: { name: '', phone: '' } }); ``` --- ## 如何選擇 - Template-Driven Forms - 宣告式,較為簡單 - 適合固定數量的表單 - 無法針對表單進行單元測試,僅能進行 E2E 測試 - Model-Driven Forms - 編成式,較為繁瑣 - 適合動態欄位數量的表單 - 後台定義的動態問卷、變動選項的投票系統 - 可以針對表單進行單元測試