AngularのForm(Reactive Forms)メモ

(Angular v.4.3.6を利用)

Reactive Formとは

Template-driven Formsとの比較

  • Template-driven Forms
    • ngModelのようなディレクティブを利用して、フォーム要素とデータモデルを紐づける。(FormControlは自動で生成されている。)入力内容が変更されるとミュータブルなデータモデルが更新される。
  • Reactive Form
    • 最初にFormControlのツリーを生成する。フォームとの紐付けはformControlNameプロパティなどでおこなう。

Template-driven Forms

<form #heroForm="ngForm">
  <input type="text" [(ngModel)]="model.name" name="name">
</form>

Reactive Forms

<form [formGroup]="heroForm">
  <input formControlName="name">
</form>
import { FormControl, FormGroup } from '@angular/forms';
...
heroForm = new FormGroup({
  name: new FormControl()
});

主要4クラス

  • AbstractControl
    • 基本クラス。他3クラスはこの抽象クラスをextendsしている。
  • FormControl
    • 個々のフォーム要素(<input>など)の値と有効性の状態を追跡
  • FormGroup
    • AbstractControlのグループの値と有効性の状態を追跡
  • FormArray
    • AbstractControlの配列の値と有効性の状態を追跡

FormGroup, FormArrayを利用した例

f:id:ryotah:20170831210750p:plain

<form [formGroup]="heroForm">
  <div>
    <label>Name:
      <input formControlName="name">
    </label>
  </div>

  <!-- アドレスの数は可変 -->
  <div formArrayName="addresses">
    <div *ngFor="let address of addresses.controls; let i=index" [formGroupName]="i">
      <div><b>Address {{i  + 1}}</b></div>
      <label>City:
        <input formControlName="city">
      </label>
    </div>
  </div>
  <button (click)="addAddress()">add</button>
</form>
<pre>Form value: {{ heroForm.value | json }}</pre>
<pre>Form status: {{ heroForm.status | json }}</pre>
heroForm: FormGroup;
constructor(private fb: FormBuilder) {

  // `FormBuilder`を利用した`FormGroup`の生成
  // https://angular.io/guide/reactive-forms#introduction-to-formbuilder
  this.heroForm = this.fb.group({
    name: '',
    addresses: this.fb.array([]),
  });
}

addAddress() {
  this.addresses.push(this.fb.group({ city: '' }));
}

get addresses(): FormArray {

  // 個々の`FormControl`, `FormGroup`, `FormArray`は `get`で取得する
  // https://angular.io/guide/reactive-forms#inspect-formcontrol-properties
  return this.heroForm.get('addresses') as FormArray;
}

フォームの値を変更する

フォームの変更を監視する

const nameControl = this.heroForm.get('name');
nameControl.valueChanges.forEach(
  (value: string) => console.log(value)
);

データモデルとフォームモデル

  • データモデルを使いフォームモデル(FormControl)を作成
  • ユーザー操作の結果、更新されるのはフォームモデル
  • Submitなどのタイミングでフォームモデルから送信用のデータモデルを作成
  • データモデルとフォームモデルの構造は一緒である必要はない(当然、似ている方が楽ではあるが)

バリデーション

(あとで追記)