博客 / 詳情

返回

Angular Form (響應式Form) 學習筆記

Angular 響應式表單使用顯式的、不可變的方式,管理表單在特定的時間點上的狀態。對錶單狀態的每一次變更都會返回一個新的狀態,這樣可以在變化時維護模型的整體性。響應式表單是圍繞 Observable 流構建的,表單的輸入和值都是通過這些輸入值組成的流來提供的,它可以同步訪問。

響應式表單通過對數據模型的同步訪問提供了更多的可預測性,使用 Observable 的操作符提供了不可變性,並且通過 Observable 流提供了變化追蹤功能。

要使用響應式表單控件,就要從 @angular/forms 包中導入 ReactiveFormsModule,並把它添加到你的 NgModule 的 imports 數組中。

import { ReactiveFormsModule } from '@angular/forms';

然後,生成一個新的 FormControl 實例,並把它保存在組件中。

要註冊一個表單控件,就要導入 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('');
}

通過在你的組件類中創建這些控件,你可以直接對錶單控件的狀態進行監聽、修改和校驗。

到現在為止,我們只是在 Component 裏創建了一個 FormControl 並把它賦給 Component 類的實例。但是,Component 的模板還感知不到這個 FormControl.

我們需要修改 Component 模板文件,將模板裏某個控件同 Component FormControl 實例綁定起來。

<label for="name">Name: </label>
<input id="name" type="text" [formControl]="name">

綁定的語法:

[formControl]="<Component 中用來保存 formControl 的類實例>"

使用這種模板綁定語法,把該表單控件註冊給了模板中名為 name 的輸入元素。這樣,表單控件和 DOM 元素就可以互相通訊了:視圖會反映模型的變化,模型也會反映視圖中的變化。
這個通信是雙向的。

有時在實際開發中,我們還能看到 FormGroup 的使用例子:

Form Group 即表單組,定義了一個帶有一組控件的表單,你可以把它們放在一起管理。

就像 FormControl 的實例能讓你控制單個輸入框所對應的控件一樣,FormGroup 的實例也能跟蹤一組 FormControl 實例(比如一個表單)的表單狀態。當創建 FormGroup 時,其中的每個控件都會根據其名字進行跟蹤。

看一個 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(''),
  });
}

現在,這些獨立的表單控件被收集到了一個控件組中。這個 FormGroup 用對象的形式提供了它的模型值,這個值來自組中每個控件的值。 FormGroup 實例擁有和 FormControl 實例相同的屬性(比如 value、untouched)和方法(比如 setValue())。

我們仍需將這個 FormGroup 實例關聯到模板文件裏。

這個表單組還能跟蹤其中每個控件的狀態及其變化,所以如果其中的某個控件的狀態或值變化了,父控件也會發出一次新的狀態變更或值變更事件。該控件組的模型來自它的所有成員。在定義了這個模型之後,你必須更新模板,來把該模型反映到視圖中。

<form [formGroup]="profileForm">

  <label for="first-name">First Name: </label>
  <input id="first-name" type="text" formControlName="firstName">

  <label for="last-name">Last Name: </label>
  <input id="last-name" type="text" formControlName="lastName">

</form>

注意,就像 FormGroup 所包含的那控件一樣,profileForm 這個 FormGroup 也通過 FormGroup 指令綁定到了 form 元素,在該模型和表單中的輸入框之間創建了一個通訊層。 由 FormControlName 指令提供的 formControlName 屬性把每個輸入框和 FormGroup 中定義的表單控件綁定起來。這些表單控件會和相應的元素通訊,它們還把更改傳給 FormGroup,這個 FormGroup 是模型值的事實之源。

當然,實際開發中有另外一種實現方法:

先創建一個空的 FormGroup,再把後續創建的 FormControl 實例,然後通過 setControl 設置到 formGroup 裏。

  protected buildForm() {
    const form = new FormGroup({});
    form.setControl('product', new FormControl(null));

    this.form = form;
  }

模板文件的實現:

<form [formGroup]="form" class="quick-order-form-container">
  <div class="quick-order-form-input">
    <input
      formControlName="product"
      placeholder="{{ 'quickOrderForm.placeholder' | cxTranslate }}"
      type="text"
    />

更多Jerry的原創文章,盡在:"汪子熙":

user avatar u_16099277 頭像
1 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.