# 多奇 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://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
- 編成式,較為繁瑣
- 適合動態欄位數量的表單
- 後台定義的動態問卷、變動選項的投票系統
- 可以針對表單進行單元測試