angular.io Guide: Reactive Forms

この記事は、Angular の公式ドキュメントの[Reactive Forms](https://angular.io/guide/reactive-forms)の章を意訳したものです｡所々抜け落ち、翻訳モレがありますがあしからずご了承を｡
バージョン 4.3.2 のドキュメントをベースにしています｡

# Reactive Forms

リアクティブフォームは、Reactive スタイルでフォームを作成するためのAngularのテクニックです。
このガイドでは、リアクティブフォームを用いて「Heroの詳細編集」フォームを作る手順を説明していきます｡

Reactive Forms[ライブサンプル](https://angular.io/generated/live-examples/reactive-forms/final.eplnkr.html)/[ダウンロードサンプル](https://angular.io/generated/zips/reactive-forms/final.reactive-forms.zip)を試してみてください。
また、[Reactive Forms Demo](https://angular.io/generated/live-examples/reactive-forms/eplnkr.html) /[ダウンロードのサンプル版](https://angular.io/generated/zips/reactive-forms/reactive-forms.zip)を実行し、上部の「demo picker」から実装途中のサンプルを選択することもできます。

## Reactive Form について
Angularは、リアクティブフォームとテンプレート駆動フォーム、2種類のフォーム構築テクノロジーを提供しています｡
2つのテクノロジ―は、`@angular/forms` ライブラリに属しており、フォームコントロールクラスの共通セットを共有しています｡

ただ、リアクティブ型(`ReactiveFormsModule`)とテンプレート駆動型(`FormsModule`)では、哲学、プログラミングスタイル、技術において著しく異なります。

### Reactive forms（リアクティブフォーム）

Angular リアクティブスタイルは、非UIデータモデル(（通常はサーバーから取得される）間のデータフローの明示的な管理に有利なプログラミングの反応スタイルを容易にします｡リアクティブフォームは、リアクティブパターン、テスト、およびバリデーションを簡単に適用できます。

リアクティブフォームでは、コンポーネントクラスにAngularフォームコントロールオブジェクトのツリーを作成し、このガイドで説明する方法を用いて、テンプレート側のネイティブフォームコントロール要素にバインドします。

フォームクラスコントロールオブジェクトは、コンポーネントクラスで直接作成と操作ができます。コンポーネントクラスはデータモデルとフォームコントロール構造の両方に対して即座にアクセスできるため、データモデル値をフォームコントロールにプッシュして、ユーザーが変更した値を取得することができます。コンポーネントは、フォーム制御状態の変化を監視（Observe）し、それらの変化に反応することができます｡

フォームコントロールオブジェクトを直接操作することの利点の1つは、値とバリデーション状態のアップデートが[常に同期して制御](https://angular.io/guide/reactive-forms#async-vs-sync)できることです。テンプレート駆動フォームで実装した場合に時々悩まされるタイミング問題に遭遇することもありませんし、Reactiveフォームは単体テストをより簡単に書くことができます。

リアクティブパラダイムに沿って、コンポーネントはデータモデルの不変性（immutability）を保存し、元の値を純粋なソースとして扱います。コンポーネントは、データモデルを直接更新するのではなく、ユーザーの変更を抽出して外部コンポーネントまたはサービスに転送します。これらのコンポーネントまたはサービスは、保存されたものなど何かを行い、更新されたモデル状態を反映する新しいデータモデルをコンポーネントに返します。

リアクティブフォームディレクティブを使用する場合、すべてのリアクティブの原理を遵守する必要はありませんが、リアクティブプログラミング手法が容易になります。

### Template-driven forms（テンプレート駆動フォーム）

テンプレートガイドで紹介されているテンプレート駆動型は、まったく異なるアプローチです。

コンポーネントテンプレートにHTMLフォームコントロール（`<input>`や`<select>`など）を配置し、`ngModel`などのディレクティブを使用してコンポーネントのデータモデルプロパティにバインドします。

Angularフォームコントロールオブジェクトは作成しません。Angularのディレクティブは、データバインディング内の情報を使用して、ディレクティブを作成します。 データ値をプッシュしたりプルすることはありません。Angularは`ngModel`でハンドリングします。Angularは、変更されたデータモデルをユーザーの変更に合わせて更新します。

このため、`ngModel`ディレクティブは`ReactiveFormsModule`の一部ではありません。

これはコンポーネントクラスのコード量が少くて済むことを意味しますが、[テンプレート駆動フォームは非同期](https://angular.io/guide/reactive-forms#async-vs-sync)であり、より高度なシナリオ下での開発を複雑にする可能性があります。

## Async vs. sync（非同期 vs 同期）

リアクティブフォームは同期的です。テンプレート駆動フォームは非同期です。これは重要な違いです。

リアクティブフォームでは、フォームコントロールツリー全体をコードで作成します。すべてのコントロールが常に利用可能であるため、親フォームの子孫を介して値をすぐに更新したり、ドリルダウンしたりすることができます。

テンプレート駆動フォームは、フォームコントロールの作成をディレクティブに委任します。 “チェックした後に変更されました”というエラーを回避するために、これらのディレクティブはコントロールツリー全体を構築するために複数のサイクルを要します。つまり、コンポーネントクラス内からコントロールを操作する前に、チェックする必要があります。

例えば、フォームコントロールに`@ViewChild(NgForm)` クエリを挿入し、それを[`ngAfterViewInit`ライフサイクルフック](https://angular.io/guide/lifecycle-hooks#afterview)で調べると、子コントロールがないことがわかります。コントロールから値を抽出したり、バリデーションのステータスをテストしたり、新しい値に設定したりするには、まず`setTimeout`を使用してチェックを待つ必要があります。

テンプレート駆動フォームの非同期性もユニットテストを複雑にします。テストブロックを`async()`または`fakeAsync()`でラップして、まだ存在しないフォーム内の値を探す必要はありません。リアクティブフォームでは、期待どおりのものがすべて利用可能です。

## Reactive と template-driven、どっちがいいの？

どちらも「より良い」ものではありません。両者とも長所と短所を持つ、2つの異なるアーキテクチャのパラダイムです。あなたにとって最適なアプローチを選択してください。両方とも同一アプリケーション内で併用することもできます。

このリアクティブフォームガイドのバランスはリアクティブパラダイムを調査し、リアクティブフォームのテクニックのみに焦点を当てて説明します。テンプレート駆動フォームの詳細については、[フォームガイド](https://angular.io/guide/forms)を参照してください。

次のセクションでは、リアクティブフォームのデモ用にプロジェクトを設定します。その後、[Angularフォームクラス](https://angular.io/guide/reactive-forms#essentials)とそれをリアクティブフォームで実装する方法について学びます。

## セットアップ

[セットアップガイド](https://angular.io/guide/setup)の手順にしたがって、*QuickStart seed*を基にした新しいプロジェクトフォルダ（`reactive-forms`と呼ばれる）を作成しましょう｡

## データモデルを作成する

このガイドの焦点は、`Hero`を編集するリアクティブなフォームコンポーネントです｡`hero` クラスとheroデータが必要です。新しいdata-model.tsファイルをappディレクトリに作成し、下のコンテンツをそのディレクトリにコピーします。

*src/app/data-model.ts*

```
export class Hero {
  id = 0;
  name = '';
  addresses: Address[];
}

export class Address {
  street = '';
  city   = '';
  state  = '';
  zip    = '';
}

export const heroes: Hero[] = [
  {
    id: 1,
    name: 'Whirlwind',
    addresses: [
      {street: '123 Main',  city: 'Anywhere', state: 'CA',  zip: '94801'},
      {street: '456 Maple', city: 'Somewhere', state: 'VA', zip: '23226'},
    ]
  },
  {
    id: 2,
    name: 'Bombastic',
    addresses: [
      {street: '789 Elm',  city: 'Smallville', state: 'OH',  zip: '04501'},
    ]
  },
  {
    id: 3,
    name: 'Magneta',
    addresses: [ ]
  },
];

export const states = ['CA', 'MD', 'OH', 'VA'];
```

このファイルは、2つのクラスと2つの定数をエクスポートします。`Address`クラスと`Hero`クラスは、アプリケーションデータモデルを定義します。 `heroes`と`states`定数はテストデータを提供します。

## *reactive forms* コンポーネントを作る

`hero-detail.component.ts`という名前の新しいファイルを`app`ディレクトリに作成し、次のシンボルをインポートします。

*src/app/hero-detail.component.ts*

```
import { Component }              from '@angular/core';
import { FormControl }            from '@angular/forms';
```

次に、`HeroDetailComponent`メタデータを指定する`@Component`デコレータを入力します。

*src/app/hero-detail.component.ts (抜粋)*

```
@Component({
  selector: 'hero-detail',
  templateUrl: './hero-detail.component.html'
})
```

次に、`FormControl`を使用して、エクスポートされた`HeroDetailComponent`クラスを作成します。 `FormControl`は、`FormControl`インスタンスを直接作成して管理できるディレクティブです。

*src/app/hero-detail.component.ts (抜粋)*

```
export class HeroDetailComponent1 {
  name = new FormControl();
}
```

ここでは、`name`という`FormControl`を作成しています。テンプレート内では、ヒーロー名用のHTML `input` ボックスにバインドされます。

`FormControl`コンストラクタは、初期データ値、バリデータの配列、および非同期バリデータの配列の3つのオプションの引数を受け取ります。

このシンプルなコントロールにはデータやバリデータはありません。実際のアプリでは、ほとんどのフォームコントロールは両方を持っています。

> このガイドでは、`Validators`について簡単に触れています。 詳細については、[フォームバリデーション](https://angular.io/guide/form-validation)ガイドを参照してください。

## テンプレートを作成する

次に、コンポーネントのテンプレート `src/app/hero-detail.component.html` を次のマークアップとともに作成します。

*src/app/hero-detail.component.html*

```
<h2>Hero Detail</h2>
<h3><i>Just a FormControl</i></h3>
<label class="center-block">Name:
  <input class="form-control" [formControl]="name">
</label>
```

これがクラスの`FormControl`という名前に関連付ける入力であることをAngularに知らせるには、`<input>`のテンプレートに`[formControl]="name"`が必要です。

> フォームコントロールで使っているCSSクラス名は気にしなくて構いません。Bootstrap CSSに含まれているクラス名を使用しており、Angularで必要なクラス名ではありません。 このクラス名でフォームのスタイルを定義しますが、フォームのロジックには決して影響を与えません｡

## *ReactiveFormsModule* をインポートする

`HeroDetailComponent`テンプレートは、`ReactiveFormsModule`の`formControlName`ディレクティブを使用します。

このサンプルでは、`AppModule`で`HeroDetailComponent`を宣言します。したがって、`app.module.ts`で次の3つのことを行います。

1. `ReactFormsModule`および`HeroDetailComponent`にアクセスするには、JavaScriptの`import`ステートメントを使用します。
2. `ReactiveFormsModule`を`AppModule`のインポートリストに追加します。
3. `declarations`配列に`HeroDetailComponent`を追加します。

*src/app/app.module.ts (抜粋)*

```
import { NgModule }            from '@angular/core';
import { BrowserModule }       from '@angular/platform-browser';
import { ReactiveFormsModule } from '@angular/forms';  // <-- #1 import module

import { AppComponent }        from './app.component';
import { HeroDetailComponent } from './hero-detail.component'; // <-- #1 import component

@NgModule({
  imports: [
    BrowserModule,
    ReactiveFormsModule // <-- #2 add to @NgModule imports
  ],
  declarations: [
    AppComponent,
    HeroDetailComponent, // <-- #3 declare app component
  ],
  bootstrap: [ AppComponent ]
})
export class AppModule { }
```

## *HeroDetailComponent* を表示する

`AppComponent`テンプレートを修正して`HeroDetailComponent`を表示します。

*src/app/app.component.ts*

```
import { Component } from '@angular/core';

@Component({
  selector: 'my-app',
  template: `
  <div class="container">
    <h1>Reactive Forms</h1>
    <hero-detail></hero-detail>
  </div>`
})
export class AppComponent { }
```

### 必須のフォームクラス

コアフォームクラスの簡単な説明を読むと役立つ場合があります。

- *[AbstractControl](https://angular.io/api/forms/AbstractControl)*は、3つの具体的なフォームコントロールクラス（`FormControl`、`FormGroup`、および`FormArray`）の抽象基本クラスです。 それは共通の振る舞いと性質を提供し、そのいくつかは観察可能である。
- *[FormControl](https://angular.io/api/forms/FormControl)*は、個々のフォームコントロールの値と有効性の状態を追跡します。 これは、入力ボックスやセレクタなどのHTMLフォームコントロールに対応します。
- *[FormGroup](https://angular.io/api/forms/FormGroup)*は、`AbstractControl`インスタンスのグループの値と有効性の状態を追跡します。 グループのプロパティには、子コントロールが含まれます。 コンポーネントの最上位フォームは`FormGroup`です。
- *[FormArray](https://angular.io/api/forms/FormArray)*は、数値的にインデックスされた`AbstractControl`インスタンスの配列の値と有効性の状態を追跡します。
このガイドでは、これらのクラスの詳細を学習します。

### appをスタイリングする

`AppComponent`と`HeroDetailComponent`の両方のテンプレートHTMLに Bootstrap の CSSクラスを使用しました。BootstrapのCSSスタイルシートをindex.htmlの先頭に追加します。

*index.html*

```
<link rel="stylesheet" href="https://unpkg.com/bootstrap@3.3.7/dist/css/bootstrap.min.css">
```

これですべてが結ばれたので、ブラウザは次のようなものを表示するはずです：

![Single FormControl](https://angular.io/generated/images/guide/reactive-forms/just-formcontrol.png)

## FormGroupを追加する

通常、複数の`FormControl`がある場合、それらを親`FormGroup`内に登録したいと思うでしょう。これは簡単です。`FormGroup`を追加するには、`hero-detail.component.ts`の`imports`セクションに追加します。

*src/app/hero-detail.component.ts*

```
import { Component }              from '@angular/core';
import { FormControl, FormGroup } from '@angular/forms';
```

このクラスでは、次のように、`FormControl`を`heroForm`という`FormGroup`にラップします。

*src/app/hero-detail.component.ts*

```
export class HeroDetailComponent2 {
  heroForm = new FormGroup ({
    name: new FormControl()
  });
}
```

クラスを変更したので、テンプレートに反映する必要があります。`hero-detail.component.html`を次のように置き換えて更新してください。

*src/app/hero-detail.component.html*

```
<h2>Hero Detail</h2>
<h3><i>FormControl in a FormGroup</i></h3>
<form [formGroup]="heroForm" novalidate>
  <div class="form-group">
    <label class="center-block">Name:
      <input class="form-control" formControlName="name">
    </label>
  </div>
</form>
```

ここで、単一の入力が`form`要素にあることに注目してください。`<form>`要素の`novalidate`属性は、ブラウザ側で実装されているネイティブHTMLバリデーションを実行するのを防ぎます。

`formGroup`は、既存の`FormGroup`インスタンスを受け取り、それをHTML要素に関連付けるリアクティブフォームディレクティブです。 この場合`heroForm`として保存した`FormGroup`をフォーム要素に関連付けます。

クラスに`FormGroup`が追加されたので、コンポーネントクラスの対応する`FormControl`に入力を関連付けるためのテンプレート構文を更新する必要があります。親`FormGroup`がなければ、`[formControl]="name"`はその指示文が単独で実行できる、つまり`FormGroup`に属さずに動作するため、早期に動作しました。親の`FormGroup`の場合、クラス内の正しい`FormControl`に関連付けられるために、名前入力には構文`formControlName="name"`が必要です。 この構文は、Angularが親`FormGroup`（この場合は`heroForm`）を検索し、そのグループ内で`name`という名前の`FormControl`を検索するように指示します。

> `form-group` CSSクラスは無視してください。 Bootstrap CSSライブラリが持っているCSSクラスであり、Angularのものではありません。`form-control`クラスと同様に、フォームをスタイルしますが、Angularのロジックには決して影響しません。

フォームは素晴らしいように見えます。しかしそれは動作していますか？ユーザーが名前を入力すると、値はどこに移動しますか？

## フォームモデルを見てみる

値は、グループフォームコントロールをバックアップするフォームモデルに入ります。 フォームモデルを表示するには、hero-detail.component.htmlの閉じるフォームタグの後に次の行を追加します。

*src/app/hero-detail.component.html*

```
<p>Form value: {{ heroForm.value | json }}</p>
<p>Form status: {{ heroForm.status | json }}</p>
```

`heroForm.value`はフォームモデルを返します。 `JsonPipe`にパイプを張り、モデルをブラウザのJSONとしてレンダリングします。

![JSON output](https://angular.io/generated/images/guide/reactive-forms/json-output.png)

初期名プロパティの値は空の文字列です｡`name`入力ボックスに入力し、キーストロークがJSONに表示されるのを見てください。

すばらしいです！これでフォームの基本機能を持つことができました！｡

実アプリでは、フォームが大幅に高速化します。`FormBuilder`はフォームの開発とメンテナンスを容易にします。

## *FormBuilder* について

`FormBuilder`クラスは、コントロールの作成の詳細を処理することで、繰り返しや混乱を軽減します。

`FormBuilder`を使用するには、`hero-detail.component.ts`にインポートする必要があります。

*src/app/hero-detail.component.ts (抜粋)*

```
import { Component }              from '@angular/core';
import { FormBuilder, FormGroup } from '@angular/forms';
```

このプランに沿って、`HeroDetailComponent`を読み書きするのが少し簡単なものにリファクタリングするために今すぐ使ってください：

- `heroForm`プロパティの型を`FormGroup`に明示的に宣言します。後でそれを初期化します。
- `FormBuilder`をコンストラクタに挿入します。
- `FormBuilder`を使用して`heroForm`を定義する新しいメソッドを追加します。 `createForm`と呼んでください。
- コンストラクタで`createForm`を呼び出します。

修正された`HeroDetailComponent`は次のようになります。

*src/app/hero-detail.component.ts (抜粋)*

```
export class HeroDetailComponent3 {
  heroForm: FormGroup; // <--- heroForm is of type FormGroup

  constructor(private fb: FormBuilder) { // <--- inject FormBuilder
    this.createForm();
  }

  createForm() {
    this.heroForm = this.fb.group({
      name: '', // <--- the FormControl called "name"
    });
  }
}
```

`FormBuilder.group`は、`FormGroup`を作成するファクトリメソッドです。 `FormBuilder.group`は、キーと値が`FormControl`の名前とその定義を持つオブジェクトを取ります。 この例では`name`コントロールは初期データ値で定義され、空の文字列です。

1つのオブジェクトにコントロールのグループを定義すると、コンパクトで読みやすいスタイルになります。それは`new FormControl(...)`ステートメントの等価なシリーズを書くのに勝っています。

### Validators.required

このガイドではバリデーションに深く関与していませんが、ここではリアクティブ形式で必要とされる`Validators.required`を使用する単純さを示す1つの例です。

まず、`Validators`シンボルをインポートします。

*src/app/hero-detail.component.ts (抜粋)*

```
import { Component }                          from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
```

`FormControl`という名前を必須にするには、`FormGroup`の`name`プロパティを配列に置き換えます。 最初の項目は`name`の初期値です。2番目は必要なバリデータ`Validators.required`です。

*src/app/hero-detail.component.ts (抜粋)*

```
this.heroForm = this.fb.group({
  name: ['', Validators.required ],
});
```

> リアクティブバリデータはシンプルで構成可能な関数です。バリデータをディレクティブでラッパーする必要があるテンプレート駆動フォームでは、バリデーションの設定は難しくなります。

テンプレートの下部にある診断メッセージを更新して、フォームのバリデーションステータスを表示しましょう｡

*src/app/hero-detail.component.html (抜粋)*

```
<p>Form value: {{ heroForm.value | json }}</p>
<p>Form status: {{ heroForm.status | json }}</p>
```

ブラウザでは次のように表示されます｡

![Single FormControl](https://angular.io/generated/images/guide/reactive-forms/validators-json-output.png)

`Validators.required`が機能しています。 入力ボックスに値がないため、ステータスは`INVALID`です。 入力ボックスに入力すると、ステータスが`INVALID`から`VALID`に変更されます。

実際のアプリでは、診断メッセージをユーザーフレンドリーなエクスペリエンスに置き換えます。

`Validators.required`の使用は、残りのガイドではオプションです。 同じ構成の次の各例にとどまります。

Angularフォームの検証の詳細については、[Form Validation](https://angular.io/guide/form-validation)ガイドを参照してください。

### その他のFormControls

`hero`は名前以上のものを持っています。 ヒーローには住所、スーパーパワー、時にはサイドキックがあります。

住所には状態プロパティがあります。 ユーザーは`<select>`ボックスで状態を選択し、`<option>`要素で状態を設定します。したがって、`data-model.ts`から状態をインポートしてください。

*src/app/hero-detail.component.ts (抜粋)*

```
import { Component }                          from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';

import { states } from './data-model';
```

`states`プロパティを宣言し、次のようにいくつかのアドレス`FormControls`を`heroForm`に追加します。

*src/app/hero-detail.component.ts (抜粋)*

```
export class HeroDetailComponent4 {
  heroForm: FormGroup;
  states = states;

  constructor(private fb: FormBuilder) {
    this.createForm();
  }

  createForm() {
    this.heroForm = this.fb.group({
      name: ['', Validators.required ],
      street: '',
      city: '',
      state: '',
      zip: '',
      power: '',
      sidekick: ''
    });
  }
}
```

その後、対応するマークアップをフォーム要素内の`hero-detail.component.html`に追加します。

```
<h2>Hero Detail</h2>
<h3><i>A FormGroup with multiple FormControls</i></h3>
<form [formGroup]="heroForm" novalidate>
  <div class="form-group">
    <label class="center-block">Name:
      <input class="form-control" formControlName="name">
    </label>
  </div>
  <div class="form-group">
    <label class="center-block">Street:
      <input class="form-control" formControlName="street">
    </label>
  </div>
  <div class="form-group">
    <label class="center-block">City:
      <input class="form-control" formControlName="city">
    </label>
  </div>
  <div class="form-group">
    <label class="center-block">State:
      <select class="form-control" formControlName="state">
          <option *ngFor="let state of states" [value]="state">{{state}}</option>
      </select>
    </label>
  </div>
  <div class="form-group">
    <label class="center-block">Zip Code:
      <input class="form-control" formControlName="zip">
    </label>
  </div>
  <div class="form-group radio">
    <h4>Super power:</h4>
    <label class="center-block"><input type="radio" formControlName="power" value="flight">Flight</label>
    <label class="center-block"><input type="radio" formControlName="power" value="x-ray vision">X-ray vision</label>
    <label class="center-block"><input type="radio" formControlName="power" value="strength">Strength</label>
  </div>
  <div class="checkbox">
    <label class="center-block">
      <input type="checkbox" formControlName="sidekick">I have a sidekick.
    </label>
  </div>
</form>


<p>Form value: {{ heroForm.value | json }}</p>
```

> 注意：このマークアップでは、`form-group`, `form-control`, `center-block`,  `checkbox` の多くを無視します。これらは、Angular自身が無視するBootstrap CSSクラスです。`formGroupName`属性と`formControlName`属性に注意してください。Angularディレクティブは、HTMLコントロールをコンポーネントクラスのAngular `FormGroup`および`FormControl`プロパティにバインドします。

修正されたテンプレートには、より多くのテキスト入力、`state`の選択ボックス、`power`のラジオボタン、および`sidekick`のチェックボックスが含まれています。

オプションの`value`プロパティを`[value]="state"`でバインドする必要があります。 値をバインドしないと、`select`にはデータモデルの最初のオプションが表示されます。

コンポーネントクラスは、テンプレート内の表現に関係なくコントロールプロパティを定義します｡`state`コントロール、`power`コントロール、および`sidekick`コントロールは、`name`コントロールを定義したのと同じ方法で定義します。`FormControlName`ディレクティブで`FormControl`名を指定して、これらのコントロールをテンプレートHTMLエレメントに同じ方法で関連付けます。

[ラジオボタン](https://angular.io/api/forms/RadioControlValueAccessor)、[プルダウンメニュー（select）](https://angular.io/api/forms/SelectControlValueAccessor)、および[チェックボックス](https://angular.io/api/forms/CheckboxControlValueAccessor)の詳細については、APIリファレンスを参照してください。

### ネストされたFormGroup

このフォームは大きくなって扱いにくいものになっています。関連する`FormControl`の一部を入れ子になった`FormGroup`にまとめることができます。 通り（Street）、都市、州、および郵便番号は、`FormGroup`という住所に適したプロパティです。 グループとコントロールをこのようにネストすると、データモデルの階層構造をミラーリングし、関連する一連のコントロールのバリデーションと状態の追跡に役立ちます。

`FormBuilder`を使用して、このコンポーネントの`heroForm`という1つの`FormGroup`を作成しました。 これを親の`FormGroup`としましょう。`FormBuilder`を再度使用して、アドレスコントロールをカプセル化する子`FormGroup`を作成します。 親`FormGroup`の新しいアドレスプロパティに結果を割り当てます。

*src/app/hero-detail.component.ts (抜粋)*

```
export class HeroDetailComponent5 {
  heroForm: FormGroup;
  states = states;

  constructor(private fb: FormBuilder) {
    this.createForm();
  }

  createForm() {
    this.heroForm = this.fb.group({ // <-- the parent FormGroup
      name: ['', Validators.required ],
      address: this.fb.group({ // <-- the child FormGroup
        street: '',
        city: '',
        state: '',
        zip: ''
      }),
      power: '',
      sidekick: ''
    });
  }
}
```

コンポーネントクラスのフォームコントロールの構造を変更しました。コンポーネントテンプレートに対応する調整を行う必要があります。

`hero-detail.component.html`では、アドレス関連の`FormControl`を`div`にラップします。`div`に`formGroupName`ディレクティブを追加し、それを`"address"`にバインドします。 これは、親`FormGroup`内の`heroForm`というアドレスの子`FormGroup`のプロパティです。

この変更を視覚的に明白にするには、最上部の`<h4>`ヘッダーをテキスト「*Secret Lair*」で伝えます。 新しいアドレスHTMLは次のようになります。

*src/app/hero-detail.component.html (抜粋)*

```
<div formGroupName="address" class="well well-lg">
  <h4>Secret Lair</h4>
  <div class="form-group">
    <label class="center-block">Street:
      <input class="form-control" formControlName="street">
    </label>
  </div>
  <div class="form-group">
    <label class="center-block">City:
      <input class="form-control" formControlName="city">
    </label>
  </div>
  <div class="form-group">
    <label class="center-block">State:
      <select class="form-control" formControlName="state">
        <option *ngFor="let state of states" [value]="state">{{state}}</option>
      </select>
    </label>
  </div>
  <div class="form-group">
    <label class="center-block">Zip Code:
      <input class="form-control" formControlName="zip">
    </label>
  </div>
</div>
```

これらの変更の後、ブラウザのJSON出力には、`FormGroup`というネストされたアドレスを持つ修正されたフォームモデルが表示されます。

![JSON output](https://angular.io/generated/images/guide/reactive-forms/address-group.png)

すばらしいです！あなたはグループを作ったので、テンプレートとフォームモデルがコミュニケーションしていることがわかります。

## FormControl プロパティを検証する

現時点では、フォームモデル全体をページにダンプしています。 場合によっては、特定の`FormControl`の1つの状態だけに興味がある場合もあります。

フォーム内の個々の`FormControl`を`.get()`メソッドで抽出することで検査できます。 これをコンポーネントクラス内で行うこともできますし、`{{form.value | json}}`インターポーレーションを次のように行います。

*src/app/hero-detail.component.html*

```
<p>Name value: {{ heroForm.get('name').value }}</p>
```

`FormGroup`内にある`FormControl`の状態を取得するには、ドット表記を使用してコントロールに渡します。

*src/app/hero-detail.component.html*

```
<p>Street value: {{ heroForm.get('address.street').value}}</p>
```

この方法を使用すると、次のいずれかのような`FormControl`のプロパティを表示できます。

|プロパティ|説明|
|----|----|
|`myControl.value`|`FormControl`の値|
|`myControl.status`|`FormControl`のバリデーション状態｡可能な値は、`VALID`、`INVALID`、`PENDING`、または`DISABLED`です。|
|`myControl.pristine`|ユーザーがUIの値を変更していない場合は`true`。その反対は`myControl.dirty`です。|
|`myControl.untouched`|ユーザがまだHTMLコントロールにフォーカス当てておらず、blur イベントがトリガされるまで`true`になります。その反対は`myControl.touched`です。|

[AbstractControl](https://angular.io/api/forms/AbstractControl) APIリファレンスの他の`FormControl`プロパティについて学んでください。

FormControlプロパティを確認する一般的な理由の1つは、ユーザーが有効な値を入力したことを確認することです。Angular のフォームバリデーション詳細については、[フォームバリデーション](https://angular.io/guide/form-validation)ガイドを参照してください。

## *data model*と*form model*

現時点では、フォームは空の値を表示しています。 `HeroDetailComponent`はヒーローの値を表示する必要があります。ヒーローは、おそらくリモートサーバーから取得したヒーローです。

このアプリでは、`HeroDetailComponent`は`HeroListComponent`の親からヒーローを取得します

サーバーのヒーローはデータモデルです。 `FormControl`構造体はフォームモデルです。

コンポーネントは、データモデルのヒーロー値をフォームモデルにコピーする必要があります。 重要な意味合いは2つあります。

1. 開発者は、データモデルのプロパティをフォームモデルのプロパティにマップする方法を理解する必要があります。
2. ユーザーの変更は、DOM要素からデータモデルにではなくフォームモデルに流れます。 フォームコントロールはデータモデルを更新しません。

フォームとデータモデルの構造は正確に一致する必要はありません。 特定の画面にデータモデルのサブセットを提示することがよくあります。 しかし、フォームモデルの形状がデータモデルの形状に近い場合は、作業が簡単になります。

この`HeroDetailComponent`では、2つのモデルが非常に近いです。

`data-model.ts`の`Hero`の定義を思い出してください：

*src/app/data-model.ts (クラス)*

```
export class Hero {
  id = 0;
  name = '';
  addresses: Address[];
}

export class Address {
  street = '';
  city   = '';
  state  = '';
  zip    = '';
}
```

ここでも、コンポーネントの`FormGroup`定義があります。

*src/app/hero-detail.component.ts (抜粋)*

```
this.heroForm = this.fb.group({
  name: ['', Validators.required ],
  address: this.fb.group({
    street: '',
    city: '',
    state: '',
    zip: ''
  }),
  power: '',
  sidekick: ''
});
```

ここでも、コンポーネントの`FormGroup`定義があります。これらのモデルには2つの重要な違いがあります。

- `Hero`はIDを持っています。フォームモデルは、一般的にユーザーにプライマリキーを表示しないためではありません。
- `Hero`には住所の配列を持っています。このフォームモデルは1つのアドレスしか表示せず、[以下](https://angular.io/guide/reactive-forms#form-array)で再選択します。

それにもかかわらず、2つのモデルはかなり近似しており、このアライメントが、データモデルのプロパティを`patchValue`メソッドと`setValue`メソッドを使用してフォームモデルにコピーする作業を簡単に見ていきます。

簡潔さと明快さのために`FormGroup`の定義を次のようにリファクタリングしてください。

*src/app/hero-detail-7.component.ts*

```
this.heroForm = this.fb.group({
  name: ['', Validators.required ],
  address: this.fb.group(new Address()), // <-- a FormGroup with a new address
  power: '',
  sidekick: ''
});
```

`Hero`クラスと`Address`クラスを参照できるように、`data-model`からインポートを更新するようにしてください。

*src/app/hero-detail-7.component.ts*

```
import { Address, Hero, states } from './data-model';
```

## *setValue*と*patchValue*を使用してフォームモデルを作成する

以前はコントロールを作成し、同時にその値を初期化しました。`setValue`メソッドと`patchValue`メソッドで後で値を初期化またはリセットすることもできます。

### *setValue*

`setValue`を使用すると、`FormGroup`の背後のフォームモデルと完全に一致するプロパティを持つデータオブジェクトを渡すことで、すべてのフォームコントロール値を一度に割り当てることができます。

*src/app/hero-detail.component.ts (抜粋)*

```
this.heroForm.setValue({
  name:    this.hero.name,
  address: this.hero.addresses[0] || new Address()
});
```

setValueメソッドは、フォームコントロールの値を割り当てる前にデータオブジェクトを完全にチェックします。

FormGroup構造と一致しないデータオブジェクトを受け入れることも、グループ内の任意のコントロールの値が欠けていることもあります。 このようにして、タイプミスがあったり、コントロールが正しく入れ子になっていないと、役に立つエラーメッセージを返すことがあります。 patchValueは自動的に失敗します。

一方、setValueはエラーをキャッチし、明確に報告します。

ヒーローは、その形状がコンポーネントのFormGroup構造に似ているので、ほとんどすべてのヒーローをsetValueの引数として使用できます。

あなたはヒーローの最初のアドレスのみを表示することができ、ヒーローには全くアドレスがない可能性を考慮する必要があります。 これは、データオブジェクト引数のアドレスプロパティの条件付き設定を説明しています。

*src/app/hero-detail-7.component.ts*

```
address: this.hero.addresses[0] || new Address()
```

### *patchValue*

`patchValue`を使用すると、対象のコントロールだけのキー/値ペアのオブジェクトを指定することで、`FormGroup`の特定のコントロールに値を割り当てることができます。

この例では、フォームの名前コントロールのみを設定します。

*src/app/hero-detail.component.ts (抜粋)*

```
this.heroForm.patchValue({
  name: this.hero.name
});
```

`patchValue`を使用すると、多岐にわたるデータやフォームモデルに柔軟に対応できます。 しかし、`setValue`とは異なり、`patchValue`は欠けているコントロール値をチェックすることはできず、有用なエラーを投げません。

### フォームモデル値（`ngOnChanges`）をセットするタイミング

これで、フォームモデルの値を設定する方法が分かりました。 しかし、いつそれらを設定しますか？ その答えは、コンポーネントがデータモデル値をいつ取得するかによって異なります。

このリアクティブフォームの`HeroDetailComponent`は、マスター/ディテールの`HeroListComponent`（以下で説明します）内にネストされています。 `HeroListComponent`はヒーロー名をユーザーに表示します。 ユーザーがヒーローをクリックすると、リストコンポーネントはヒーロー入力プロパティにバインドして、選択されたヒーローを`HeroDetailComponent`に渡します。

*hero-list.component.html (簡略)*

```
<nav>
  <a *ngFor="let hero of heroes | async" (click)="select(hero)">{{hero.name}}</a>
</nav>

<div *ngIf="selectedHero">
  <hero-detail [hero]="selectedHero"></hero-detail>
</div>
```

このアプローチでは、ユーザーが新しいヒーローを選択するたびに、`HeroDetailComponent`のヒーローの値が変更されます。 `ngOnChanges`フックで`setValue`を呼び出す必要があります。これは、次の手順で示すように*hero*Inputプロパティが変更されたときに呼び出されます。

まず、`hero-detail.component.ts`に`OnChanges`と`Input`シンボルをインポートします。

*src/app/hero-detail.component.ts (core imports)*

```
import { Component, Input, OnChanges }             from '@angular/core';
```

`hero` Input プロパティを追加します｡

*src/app/hero-detail-6.component.ts*

```
@Input() hero: Hero;
```

次のように`ngOnChanges`メソッドをクラスに追加します。

*src/app/hero-detail.component.ts (ngOnchanges)*

```
ngOnChanges()
  this.heroForm.setValue({
    name:    this.hero.name,
    address: this.hero.addresses[0] || new Address()
  });
}
```

### フォームフラグをリセットする

ヒーローが変更されたときにフォームをリセットして、前のヒーローのコントロール値がクリアされ、状態フラグが元の状態に復元されるようにする必要があります。 このように`ngOnChanges`の先頭でリセットを呼び出すことができます。

*src/app/hero-detail-7.component.ts*

```
this.heroForm.reset();
```

`reset`メソッドにはオプションの`state`値があるため、フラグと制御値を同時にリセットできます。 内部的には、`reset`は引数を`setValue`に渡します。 少しのリファクタリングと`ngOnChanges`がこれになります：

*src/app/hero-detail.component.ts (ngOnchanges - revised)*

```
ngOnChanges() {
  this.heroForm.reset({
    name: this.hero.name,
    address: this.hero.addresses[0] || new Address()
  });
}
```

### *HeroListComponent* と *HeroService* を作成する

`HeroDetailComponent`は、マスター/詳細ビューの`HeroListComponent`のネストされたサブコンポーネントです。これらを組み合わせると下記のように見えます: 

![HeroListComponent](https://angular.io/generated/images/guide/reactive-forms/hero-list.png)

`HeroListComponent`はinjectされた`HeroService`を使用してサーバーからヒーローを取り出し、そのヒーローを一連のボタンとしてユーザーに提示します。 `HeroService`はHTTPサービスをエミュレートします。ネットワークレイテンシをシミュレートし、視覚的にアプリケーションの必然的に非同期性を示すために、短い遅延の後に解決するヒーロー`Observable`を返します。

ユーザーがヒーローをクリックすると、コンポーネントは`HeroDetailComponent`のヒーロー入力プロパティにバインドされている`selectedHero`プロパティを設定します。 `HeroDetailComponent`は変更されたヒーローを検出し、そのヒーローのデータ値でフォームを再設定します。

「Refresh」ボタンはヒーローリストと現在選択されているヒーローをクリアしてから、ヒーローをリフレッシュします。

残りの`HeroListComponent`と`HeroService`の実装の詳細は、リアクティブフォームの理解には関係ありません。関連するテクニックは、[ここ](https://angular.io/tutorial/toh-pt3)と[ここ](https://angular.io/tutorial/toh-pt4)のHeroツアーを含むドキュメンテーションの別の場所でカバーされています。

このリアクティブフォームチュートリアルの手順に従ってコーディングする場合は、以下に示すソースコードに基づいて適切なファイルを作成します。`hero-list.component.ts`は`Observable`と`finally`をインポートし、`hero.service.ts`が`rxjs`から`Observable`、`of`、および`Delay`をインポートする間にインポートされます。その後、ここに戻り、フォーム配列のプロパティについて学びます。

## `FormArray`を使用して`FormGroup`の配列を表示する

これまで、`FormControls`と`FormGroup`を見てきました。`FormGroup`は、プロパティ値が`FormControls`および他の`FormGroups`である名前付きオブジェクトです。

場合によっては、任意の数のコントロールやグループを表示する必要があります。 たとえば、主人公はゼロ、1つ、または任意の数のアドレスを持つことができます。

`Hero.addresses`プロパティは、`Address`インスタンスの配列です。 アドレス`FormGroup`は1つのアドレスを表示できます。 Angular `FormArray`は、`FormGroups`のアドレスの配列を表示できます。

`FormArray`クラスにアクセスするには、`hero-detail.component.ts`にインポートします。

*src/app/hero-detail.component.ts (抜粋)*

```
import { Component, Input, OnChanges }                   from '@angular/core';
import { FormArray, FormBuilder, FormGroup, Validators } from '@angular/forms';

import { Address, Hero, states } from './data-model';
```

FormArrayを操作するには、次の手順を実行します。

1. 配列に項目（`FormControls`または`FormGroups`）を定義します。
1. データモデル内のデータから作成された項目を使用して配列を初期化します。
1. ユーザーが必要とするアイテムを追加して削除します。

このガイドでは、`Hero.address`用の`FormArray`を定義し、ユーザーがアドレスを追加または変更できるようにします（アドレスの削除は宿題とします）。

`HeroDetailComponent`コンストラクタでフォームモデルを再定義する必要があります。コンストラクタは現在、`FormGroup`のアドレスに最初のヒーローアドレスのみを表示します。

*src/app/hero-detail-7.component.ts*

```
this.heroForm = this.fb.group({
  name: ['', Validators.required ],
  address: this.fb.group(new Address()), // <-- a FormGroup with a new address
  power: '',
  sidekick: ''
});
```

### *address*から*secret lairs(秘密の寝室)*まで
ユーザーの視点から見ると、ヒーローには住所がありません。住所は単なる死人のためのものです。英雄は秘密の寝所を持っています！`FormGroup`定義の住所を*secretLairs* `FormArray`定義に置き換えます。

*src/app/hero-detail-8.component.ts*

```
this.heroForm = this.fb.group({
  name: ['', Validators.required ],
  secretLairs: this.fb.array([]), // <-- secretLairs as an empty FormArray
  power: '',
  sidekick: ''
});
```

> フォーム制御名を`address`から`secretLairs`に変更することは、重要なポイントです。フォームモデルはデータモデルと一致する必要はありません。
> 明らかに両者の間には関係がなければなりません｡しかし、アプリケーションドメイン内では意味をなさないものになる可能性があります。
> プレゼンテーション要件は、データ要件とはしばしば異なります｡リアクティブ型のアプローチは、この区別を強調し、容易にします。

### "secretLairs" *FormArray* を初期化する

デフォルトのフォームでは、アドレスのない名前のないヒーローが表示されます。

親`HeroListComponent`が`HeroListComponent.hero`入力プロパティを新しい`Hero`に設定するたびに、*secretLairs*に実際のヒーローアドレスを設定する（または再投入する）メソッドが必要です。

次の`setAddresses`メソッドは、*secretLairs* `FormArray`を*hero*の住所が格納された`FormGroups`配列で初期化された新しい`FormArray`に置き換えます。

*src/app/hero-detail-8.component.ts*

```
setAddresses(addresses: Address[]) {
  const addressFGs = addresses.map(address => this.fb.group(address));
  const addressFormArray = this.fb.array(addressFGs);
  this.heroForm.setControl('secretLairs', addressFormArray);
}
```

以前の`FormArray`を`setValue`ではなく`FormGroup.setControl`メソッドで置き換えることに注目してください。あなたは、コントロールの値ではなく、コントロールを置き換えています。

また、*secretLairs* `FormArray`には`Addresses`ではなく`FormGroups`が含まれています。

### *FormArray* を取得する

`HeroDetailComponent`は、*secretLairs* `FormArray`からアイテムを表示、追加、および削除できる必要があります。

`FormGroup.get`メソッドを使用して、その`FormArray`への参照を取得します。明快さと再利用のために、式を`secretLairs`コンビニエンスプロパティにラップします。

### *FormArray* を表示する

現在のHTMLテンプレートは単一のアドレス`FormGroup`を表示します。ヒーローの住所`FormGroups`の0、1つ、またはそれ以上を表示するように修正します。

これは主に、前のテンプレートHTMLを`<div>`内のアドレスにラップし、その`<div>`を`* ngFor`で繰り返すことです。

そのトリックは`*ngFor`の書き方を知ることにあります。3つの重要なポイントがあります：

1. 別の折り返し`<div>`を`*ngFor`で`<div>`の周りに追加し、その`formArrayName`ディレクティブを "secretLairs" に設定します。この手順は、内側の繰り返しHTMLテンプレートのフォームコントロールのコンテキストとして*secretLairs* `FormArray`を確立します。
2. 繰り返されるアイテムのソースは、`FormArray`自体ではなく、`FormArray.controls`です。各コントロールは`FormGroup`というアドレスです。これは以前の（今度は繰り返された）テンプレートのHTMLとまったく同じです。
3. `FormGroup`を繰り返すたびに、`FormArray`内の`FormGroup`のインデックスでなければならない固有の`formGroupName`が必要です。このインデックスを再利用して、各アドレスの一意のラベルを作成します。

HTMLテンプレートの*secret lairs*セクションの骨組みは次のとおりです。

*src/app/hero-detail.component.html (*ngFor)*

```
<div formArrayName="secretLairs" class="well well-lg">
  <div *ngFor="let address of secretLairs.controls; let i=index" [formGroupName]="i" >
    <!-- The repeated address template -->
  </div>
</div>
```

*secret lairs*のセクションの完全なテンプレートは次のとおりです。

*src/app/hero-detail.component.html (抜粋)*

```
<div formArrayName="secretLairs" class="well well-lg">
  <div *ngFor="let address of secretLairs.controls; let i=index" [formGroupName]="i" >
    <!-- The repeated address template -->
    <h4>Address #{{i + 1}}</h4>
    <div style="margin-left: 1em;">
      <div class="form-group">
        <label class="center-block">Street:
          <input class="form-control" formControlName="street">
        </label>
      </div>
      <div class="form-group">
        <label class="center-block">City:
          <input class="form-control" formControlName="city">
        </label>
      </div>
      <div class="form-group">
        <label class="center-block">State:
          <select class="form-control" formControlName="state">
            <option *ngFor="let state of states" [value]="state">{{state}}</option>
          </select>
        </label>
      </div>
      <div class="form-group">
        <label class="center-block">Zip Code:
          <input class="form-control" formControlName="zip">
        </label>
      </div>
    </div>
    <br>
    <!-- End of the repeated address template -->
  </div>
</div>
```

### *FormArray* に新しい寝所を追加する

`addLair`メソッドを追加して、*secretLairs* `FormArray`を取得し、新しいアドレス`FormGroup`を追加します。

*src/app/hero-detail.component.ts (addLair メソッド)*

```
addLair() {
  this.secretLairs.push(this.fb.group(new Address()));
}
```

フォーム上にボタンを配置すると、ユーザーは新しい*秘密の寝所*を追加し、それをコンポーネントの`addLair`メソッドに渡すことができます。

*src/app/hero-detail.component.html (addLair button)*

```
<button (click)="addLair()" type="button">Add a Secret Lair</button>
```

> `type="button"`属性を必ず追加してください。実際にはボタンの`type`を常に指定する必要があります。明示的な型がなければ、ボタンタイプはデフォルトで"submit"になります。 後でフォーム送信アクションを追加すると、すべての「送信」ボタンが送信アクションをトリガーし、現在の変更を保存するようなことが起きる可能性があります。 ユーザーが*Add a Secret Lair*ボタンをクリックしたときに、変更内容を保存する必要はありません。

### Try it!

ブラウザーに戻って、「Magneta」という名の英雄を選択します。 フォームの下部にある診断JSONに表示されているように、「Magneta」にはアドレスはありません。

![JSON output of addresses array](https://angular.io/generated/images/guide/reactive-forms/addresses-array.png)

[Add a Secret Lair]ボタンをクリックします。 新しいアドレスセクションが表示されます。よく頑張りました！

### ねぐらを削除する

この例ではアドレスを追加できますが、アドレスは削除できません。さらなる信頼のために、*removeLair*メソッドを記述し、それを繰り返しアドレスHTMLのボタンにつなぎましょう｡

### コントロールの変更を監視する

Angularは、ユーザーが親`HeroListComponent`のヒーローを選択したときに`ngOnChanges`を呼び出します。 ヒーローを選ぶと、`HeroDetailComponent.hero` Inputプロパティが変更されます。

Angularは、ユーザーがヒーローの名前または秘密の兵士を変更したときに`ngOnChanges`を呼び出しません。 幸いにも、変更イベントを発生させるフォームコントロールプロパティの1つにsubscribeすることで、そのような変更について知ることができます。

これらは、RxJS `Observable`を返し、`valueChanges`などのプロパティです。 フォーム制御値を監視するためにRxJS `Observable`について多くのことを知る必要はありません。

`FormControl`という名前の値の変更を記録する次のメソッドを追加します。

*src/app/hero-detail.component.ts (logNameChange)*

```
nameChangeLog: string[] = [];
logNameChange() {
  const nameControl = this.heroForm.get('name');
  nameControl.valueChanges.forEach(
    (value: string) => this.nameChangeLog.push(value)
  );
}
```

フォームを作成した後、コンストラクターで呼び出します。

*src/app/hero-detail-8.component.ts*

```
constructor(private fb: FormBuilder) {
  this.createForm();
  this.logNameChange();
}
```

`logNameChange`メソッドは、名前変更値を`nameChangeLog`配列にプッシュします。 この`*ngFor`バインディングを使ってコンポーネントテンプレートの一番下に配列を表示します：

*src/app/hero-detail.component.html (Name change log)*

```
<h4>Name change log</h4>
<div *ngFor="let name of nameChangeLog">{{name}}</div>
```

ブラウザに戻り、ヒーロー（たとえば「マゼンタ」）を選択し、名前入力ボックスに入力を開始します。 各キーストローク後にログに新しい名前が表示されます。

### それはいつ使うの？

インターポーレーション バインディングは、名前の変更を表示する簡単な方法です。観察可能なフォームコントロールプロパティを購読することは、コンポーネントクラス内のアプリケーションロジックをトリガーするのに便利です。

## データを保存する

`HeroDetailComponent`はユーザーの入力をキャプチャしますが、何もしません。 実際のアプリでは、おそらくそれらのヒーローの変更を保存します。 実際のアプリでは、保存していない変更を元に戻して編集を再開することもできます。 このセクションで両方の機能を実装すると、フォームは次のようになります。

![Form with save & revert buttons](https://angular.io/generated/images/guide/reactive-forms/save-revert-buttons.png)

### 保存

このサンプルアプリケーションでは、ユーザーがフォームを送信すると、`HeroDetailComponent`はヒーローデータモデルのインスタンスを、injectされた`HeroService`の`save`メソッドに渡します。

*src/app/hero-detail.component.ts (onSubmit)*

```
onSubmit() {
  this.hero = this.prepareSaveHero();
  this.heroService.updateHero(this.hero).subscribe(/* error handling */);
  this.ngOnChanges();
}
```

このオリジナルの`hero`には保存前の値がありました。 ユーザーの変更はまだフォームモデルにあります。したがって、オリジナルのヒーロー値（`hero.id`）と、変更されたフォームモデル値の詳細コピー（`prepareSaveHero`ヘルパーを使用）の組み合わせから新しいヒーローを作成します。

*src/app/hero-detail.component.ts (prepareSaveHero)*

```
prepareSaveHero(): Hero {
  const formModel = this.heroForm.value;

  // deep copy of form model lairs
  const secretLairsDeepCopy: Address[] = formModel.secretLairs.map(
    (address: Address) => Object.assign({}, address)
  );

  // return new `Hero` object containing a combination of original hero value(s)
  // and deep copies of changed form model values
  const saveHero: Hero = {
    id: this.hero.id,
    name: formModel.name as string,
    // addresses: formModel.secretLairs // <-- bad!
    addresses: secretLairsDeepCopy
  };
  return saveHero;
}
```

> **Address deep copy**
> 
> `formModel.secretLair`を`saveHero.addresses`（コメント行を参照）に割り当てていた場合、`saveHero.addresses`配列のアドレスは`formModel.secretLairs`の椅子と同じオブジェクトになります。その後のユーザーの恋人の通りへの変更は、`saveHero`の住所の通りを変更することになります。
> 
> `prepareSaveHero`メソッドは、フォームモデルの`secretLairs`オブジェクトのコピーを生成しないようにします。

### 取り消し（変更のキャンセル）

*Revert*ボタンを押すと、ユーザーは変更をキャンセルし、フォームを元の状態に戻します。 元に戻すのは簡単です。オリジナルの変更されていないヒーローデータモデルからフォームモデルを構築した`ngOnChanges`メソッドを再実行するだけです。

*src/app/hero-detail.component.ts (revert)*

```
revert() { this.ngOnChanges(); }
```

### ボタン

コンポーネントのテンプレートの上部にある「Save」ボタンと「Revert」ボタンを追加します。

*src/app/hero-detail.component.html (Save and Revert buttons)*

```
<form [formGroup]="heroForm" (ngSubmit)="onSubmit()" novalidate>
  <div style="margin-bottom: 1em">
    <button type="submit"
            [disabled]="heroForm.pristine" class="btn btn-success">Save</button> &nbsp;
    <button type="reset" (click)="revert()"
            [disabled]="heroForm.pristine" class="btn btn-danger">Revert</button>
  </div>

  <!-- Hero Detail Controls -->
  <div class="form-group radio">
    <h4>Super power:</h4>
    <label class="center-block"><input type="radio" formControlName="power" value="flight">Flight</label>
    <label class="center-block"><input type="radio" formControlName="power" value="x-ray vision">X-ray vision</label>
    <label class="center-block"><input type="radio" formControlName="power" value="strength">Strength</label>
  </div>
  <div class="checkbox">
    <label class="center-block">
      <input type="checkbox" formControlName="sidekick">I have a sidekick.
    </label>
  </div>
</form>
```

フォームコントロール（`heroForm.dirty`）のいずれかの値を変更してフォームを「Dirty」にするまで、ボタンは無効になります。

タイプ「`submit`」のボタンをクリックすると、コンポーネントの`onSubmit`メソッドを呼び出す`ngSubmit`イベントがトリガされます。Revert ボタンをクリックすると、コンポーネントの`revert`メソッドが呼び出されます。ユーザーは変更を保存または元に戻すことができます。

これはデモの最後のステップです。 [Reactive Forms（final）を Plunker で試す](https://angular.io/generated/live-examples/reactive-forms/final.eplnkr.html)か、[サンプルをダウンロード](https://angular.io/generated/zips/reactive-forms/final.reactive-forms.zip)してください｡

## まとめ

このページでは下記の内容を紹介しました｡

- リアクティブフォームコンポーネントとそれに対応するテンプレートを作成する方法。
- `FormBuilder`を使用してリアクティブフォームのコードを簡単にする方法。
- `FormControls`のグループ化。
- `FormControl`プロパティの検査。
- `patchValue`と`setValue`でデータを設定する。
- `FormArray`で動的にグループを追加する。
- `FormControl`の値に対する変更を観察します。
- フォームの変更の保存します。

最終バージョンのファイルは次のとおりです。

*（省略）*

このガイドのすべての手順の完全なソースは、[Reactive Forms Demo](https://angular.io/generated/live-examples/reactive-forms/eplnkr.html)／[ダウンロードサンプル]()のライブサンプルからダウンロードできます。