理解Angular的Reactive Form

sanshine發表於2018-02-25

原文連結

官方文件並沒有說明Template-driven FormReactive Form 哪一個更好。由於之前開發過一個Ionic2專案,使用的是Template-driven Form,光是校驗就有一坨程式碼,維護與開發簡直慘不忍睹,所以個人更加推薦使用Reactive Form

使用Reactive Form(同步),我們會在程式碼中建立整個表單 form control 樹。我們可以立即更新一個值或者深入到表單中的任意節點,因為所有的 Form control 都始終是可用的。而且因為是同步,有利於單元測試。

Template-driven Form(非同步)中,我們是通過指令來建立 form control 的。我們在操作一個Form control之前,必須要經歷一個變化檢測週期。

FormControl、FormGroup、FormArray

FormControl是最小單位(C),FormGroup類似於一個由FormControl(C)元件的object物件(G),FormArray(A)是一個由FormGroup(G)的Array陣列。它們之間可以互相巢狀,以應對各式各樣的表單模型(Form Model)。

  addForm: FormGroup;

  constructor(public formBuilder: FormBuilder) {
    this.orderForm = this.formBuilder.group({
      name: ['', [Validators.required]],
      description: ['', [Validators.required]],
      other: this.formBuilder.group({
        name: ['', [Validators.required]],
        description: ['', [Validators.required]]
      }),
      items: this.formBuilder.array([
        this.formBuilder.group({
          name: ['', [Validators.required]],
          description: ['', [Validators.required]],
        }),
        this.formBuilder.group({
          name: ['', [Validators.required]],
          description: ['', [Validators.required]],
        }),
        this.formBuilder.group({
          name: ['', [Validators.required]],
          description: ['', [Validators.required]],
        })
      ])
    });
  }
  
複製程式碼

通過this.addForm.value獲取的值:

{
  name:'',
  description:'',
  other: {
    name:'',
    description:'',
  },
  items: [
    {
      name:'',
      description:'',
    },
    {
      name:'',
      description:'',
    },
    {
      name:'',
      description:'',
    }
  ]
}
複製程式碼

它們三者之間的關係如下:

formGroup = 
{
  formControlName:formControl,
  formControlName:formControl,
  formControlName:formControl,
}

formArray = [
  formGroup,
  formGroup,
]= [
    {
      formControlName:formControl,
      formControlName:formControl,
      formControlName:formControl,
    },
    {
      formControlName:formControl,
      formControlName:formControl,
      formControlName:formControl,
    }
]
複製程式碼

對於使用Reactive Form時,動態增加formControl也是很方便的。這種在,比如新增出差明細等情況下很適合。 程式碼示例參考

data model與form model

來自伺服器就是資料模型(data model),而FormControl的結構就是表單模型(form model)。

元件必須把資料模型中的英雄值複製到表單模型中。這裡隱含著兩個非常重要的點。

  • 開發人員必須理解資料模型是如何對映到表單模型中的屬性的。
  • 使用者修改時的資料流是從DOM元素流向表單模型的,而不是資料模型。表單控制元件永遠不會修改資料模型。

個人經驗:

  1. 按照如此的劃分,從來可以不依賴後端的資料結構(畢竟後端的資料格式是千奇百怪的)。
  2. 表單模型最好和要提交的資料格式一樣,資料的修改都是操作表單模型的 formControl。提交的時候不需要手動組裝資料。
  3. 由於之前的專案使用的是Template-driven Form,需要手動組裝提交的資料,而且並沒有嚴格區分資料模型與表單模型,後期維護時,程式碼很亂。
  4. 儘量使用型別系統,不要圖方便使用any,不然維護的時候,這酸爽!!!

setValue 與 patchValue

  • setValue: 使用的時候需要每個from control都要設定值。否則,ERROR Error: Must supply a value for form control with name: 'xxxxx'
  • patchValue: 類似打補丁,不需要每個from control都要設定值。

相關文章