ryotah.hatenablog.com 別記事でこんなのも書きました。
(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() });
- https://angular.io/guide/reactive-forms#reactive-forms-1
One advantage of working with form control objects directly is that value and validity updates are always synchronous and under your control.
- https://angular.io/guide/reactive-forms#async-vs-sync
Reactive forms are synchronous. Template-driven forms are asynchronous.
主要4クラス
- AbstractControl
- 基本クラス。他3クラスはこの抽象クラスをextendsしている。
- FormControl
- 個々のフォーム要素(
<input>
など)の値と有効性の状態を追跡
- 個々のフォーム要素(
- FormGroup
AbstractControl
のグループの値と有効性の状態を追跡
- FormArray
AbstractControl
の配列の値と有効性の状態を追跡
FormGroup
, FormArray
を利用した例
<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; }
フォームの値を変更する
- AbstractControl#setValue
- AbstractControl#patchValue
- AbstractControl#reset
- FormGroup#setControl
- 既にあるcontrolを置き換える
- FormArray#setControl
- 既にあるcontrolを置き換える
フォームの変更を監視する
const nameControl = this.heroForm.get('name'); nameControl.valueChanges.forEach( (value: string) => console.log(value) );
データモデルとフォームモデル
- データモデルを使いフォームモデル(
FormControl
)を作成 - ユーザー操作の結果、更新されるのはフォームモデル
- Submitなどのタイミングでフォームモデルから送信用のデータモデルを作成
- データモデルとフォームモデルの構造は一緒である必要はない(当然、似ている方が楽ではあるが)
バリデーション
(あとで追記)