angular.io Guide: Template-driven Forms (Forms)

これは、Angular の公式ドキュメントの [Forms](https://angular.io/guide/forms) の章 を意訳したものです｡
駆け足で翻訳したので至らない点もありますが、あしからずご承知おきください｡

バージョン 4.3.1 のドキュメントをベースにしています｡

# Forms (Template-driven Forms)

フォームはビジネスアプリケーションの大黒柱です。フォームを使用してログインし、ヘルプリクエストを送信したり、注文したり、フライトを予約したり、ミーティングをスケジュールしたり・・・その他の無数のデータ入力タスクを実行します。

フォームを開発するには、ワークフローを通じて効率的かつ効果的にユーザーを誘導するデータ入力エクスペリエンスを作成することが重要です。

フォームを開発するには、設計スキル（このページでは説明の対象外です）と双方向データバインディング、変更の追跡、検証、エラー処理のフレームワークサポートが必要です。

このページでは、単純なフォームを最初から作成する方法を示します。途中で次のことを学びます：

- コンポーネントとテンプレートを使用してAngularフォームを作成します。
- `ngModel` を使用して、入力制御値を読み書きするための双方向データバインディングを作成します。
- 状態の変化とフォームコントロールの有効性を追跡します。
- コントロールの状態を追跡する特別なCSSクラスを使用して視覚的フィードバックを提供します。
- バリデーションエラーをユーザーに表示し、フォームコントロールを有効または無効にします。
- テンプレート参照変数を使用してHTML要素間で情報を共有します。

Plunkerで[ライブサンプル](https://angular.io/generated/live-examples/forms/eplnkr.html)を見るか/[こちらからサンプルをダウンロード](https://angular.io/generated/zips/forms/forms.zip)を実行することができます。

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

このページに記載されているフォーム固有の指示とテクニックを使用して、Angular [テンプレート構文](https://angular.io/guide/template-syntax)でテンプレートを記述することにより、フォームを構築できます。

> Reactive型（またはモデル駆動型）アプローチを使用してフォームを構築することもできますが、このページではテンプレート駆動フォームに焦点を当てています。

Angularテンプレートを使用してほぼすべてのフォームを作成できます - ログインフォーム、連絡フォーム、ほぼすべてのビジネスフォームを作成できます｡
コントロールをクリエイティブにレイアウトし、データにバインドし、バリデーションルールを指定し、バリデーションエラーを表示し、特定のコントロールを条件付きで有効または無効にしたり、ビジュアルフィードバックをトリガしたりできます。

Angularは、あなた自身が苦労している繰り返しの多い定型的なタスクの多くを処理することで、プロセスを簡単にします。

次のようなテンプレート駆動型フォームを構築する方法を学びます：

![Clean Form](https://angular.io/generated/images/guide/forms/hero-form-1.png)

「Hero Employment Agency」は、このフォームを使用してヒーローに関する個人情報を管理しています。すべてのヒーローは仕事が必要です。 適切なヒーローに正しい危機をアサインして一致させることが、会社のミッションです。

このフォームの3つのフィールドのうちの2つが必須です。 必須フィールドには、左側に緑色のバーが表示されます。

ヒーロー名を削除すると、フォームは注意を引くスタイルでバリデーションエラーを表示します。

![Invalid, Name Required](https://angular.io/generated/images/guide/forms/hero-form-2.png)

Submitボタンは無効になっており、入力コントロールの左側の「必須」バーが緑色から赤色に変わります。

> 標準のCSSを使用して、「必須」バーの色と位置をカスタマイズできます。

このフォームは小さな手順で作成します：

1. `Hero` モデルクラスを作成します。
1. フォームを制御するコンポーネントを作成します。
1. 最初のフォームレイアウトでテンプレートを作成します。
1. `ngModel` 双方向のデータバインディング構文を使用して各フォームコントロールにデータプロパティをバインドします。
1. 各フォーム入力コントロールに`name`属性を追加します。
1. 視覚的なフィードバックを提供するカスタムCSSを追加します。
1. 検証エラーメッセージの表示と非表示を切り替えます。
1. `ngSubmit` でフォームの送信を処理します。
1. フォームが有効になるまで、フォームの[送信]ボタンを無効にします。

## セットアップ

[Setup](https://angular.io/guide/setup) の方法に従って、angle-forms という名前の新しいプロジェクトを作成します。

## ヒーローモデルクラスを作成する

ユーザーがフォームデータを入力すると、その変更をキャプチャしてモデルのインスタンスを更新します。モデルがどのように見えるかを知るまで、フォームをレイアウトすることはできません。

モデルは、アプリケーションの重要性に関する事実を保持する「プロパティバッグ」と同じくらいシンプルにすることができます。3つの必須フィールド（`id`, `name`, `power`）と1つのオプションフィールド（`alterEgo`）を持った`Hero`クラスについて説明しています。

appディレクトリに、指定されたコンテンツを含む次のファイルを作成します。

*src/app/hero.ts*

```
export class Hero {

  constructor(
    public id: number,
    public name: string,
    public power: string,
    public alterEgo?: string
  ) {  }

}
```

これは、要件がほとんどなく振る舞いのない貧弱なモデルです｡デモ用には最適ですね。

TypeScriptコンパイラは、パブリックコンストラクタパラメータごとにパブリックフィールドを生成し、ヒーローを作成するときにそのフィールドにパラメータの値を自動的に割り当てます。

`alterEgo`はオプションであるため、コンストラクタで省略することができます。`alterEgo?`の疑問符(?)を気に留めておいてください｡

あなたは次のように新しいヒーローを作ることができます：

*src/app/hero-form.component.ts (SkyDog)*

```
let myHero =  new Hero(42, 'SkyDog',
                       'Fetch any object at any distance',
                       'Leslie Rollover');
console.log('My hero is called ' + myHero.name); // "My hero is called SkyDog"
```

## フォームコンポーネントを作成する

Angularフォームには、HTMLベースのテンプレートと、データとユーザー対話をプログラムで処理するコンポーネントクラスの2つの部分があります。 主人公の編集者ができることを簡単に述べるので、クラスから始めましょう。

指定した内容で次のファイルを作成します。

*src/app/hero-form.component.ts (v1)*

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

import { Hero }    from './hero';

@Component({
  selector: 'hero-form',
  templateUrl: './hero-form.component.html'
})
export class HeroFormComponent {

  powers = ['Really Smart', 'Super Flexible',
            'Super Hot', 'Weather Changer'];

  model = new Hero(18, 'Dr IQ', this.powers[0], 'Chuck Overstreet');

  submitted = false;

  onSubmit() { this.submitted = true; }

  // TODO: Remove this when we're done
  get diagnostic() { return JSON.stringify(this.model); }
}
```

このコンポーネントには特別なものはありません。フォーム固有のコンポーネントはありません。これまでに書いたコンポーネントと区別するものはありません。

このコンポーネントを理解するには、前のページで説明したAngularの概念のみが必要です。

- コードはAngularコアライブラリと作成した`Hero`モデルをインポートします。
- "hero-form"という `@Component` セレクタの値は、このフォームを `<hero-form>` タグを持つ親テンプレートにドロップできることを意味します。
- `templateUrl` プロパティは、テンプレートHTMLの別のファイルを指し示します。
- デモにふさわしい`model`と`powers`のためのダミーデータを定義しました。

実際のデータを取得して保存するためのデータサービスを挿入したり、親コンポーネントへのバインディングのためにこれらのプロパティを入力と出力として公開したりすることができます（[テンプレート構文](https://angular.io/guide/template-syntax)ページ内の[入出力プロパティ](https://angular.io/guide/template-syntax#inputs-outputs)を参照）。これは現在懸念されておらず、これらの将来の変更はフォームに影響しません。

モデルのJSON表現を返すための診断プロパティを追加しました。開発中に何をしているのかを理解するのに役立ちます。あなたはそれを後で破棄するためのクリーンアップノートを残しています。

## なぜフォームを別のテンプレートファイルにしているのですか？

他の場所でよく使うように、コンポーネントファイルにテンプレートをインラインで書くのはなぜですか？

すべての機会に「正しい」答えはありません。インラインテンプレートは、短い場合に便利です。ほとんどのフォームテンプレートは短くありません。 TypeScriptファイルとJavaScriptファイルは、一般的にHTMLの大部分を書く（または読み込む）のに最適な場所ではなく、HTMLとコードが混在したファイルを扱えるエディタはほとんどありません。

少数のフィールドを表示する場合でも、フォームテンプレートは大きくなる傾向があります。そのため、通常HTMLテンプレートを別のファイルに配置することをお勧めします。そのテンプレートファイルをすぐに書きます。まず、新しいHeroFormComponentを使用するように`app.module.ts`と`app.component.ts`を修正します。

## app.module.tsを修正する

`app.module.ts` は、アプリケーションのルートモジュールを定義します。その中で、アプリケーションで使用する外部モジュールを特定し、このモジュールに属するコンポーネント（`HeroFormComponent` など）を宣言します。

テンプレート駆動フォームは独自のモジュールにあるため、フォームを使用する前に、アプリケーションモジュールのインポート配列に`FormsModule`を追加する必要があります。

「QuickStart」バージョンの内容を次のものに置き換えます。

*src/app/app.module.ts*

```
import { NgModule }      from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule }   from '@angular/forms';

import { AppComponent }  from './app.component';
import { HeroFormComponent } from './hero-form.component';

@NgModule({
  imports: [
    BrowserModule,
    FormsModule
  ],
  declarations: [
    AppComponent,
    HeroFormComponent
  ],
  bootstrap: [ AppComponent ]
})
export class AppModule { }
```

> 3つの変更点があります。
>
> 1. `FormsModule`と新しい`HeroFormComponent`をインポートします。
> 1. `FormsModule`を`@NgModule`デコレータで定義されたインポートのリストに追加します。これにより、アプリケーションは、`ngModel`を含むすべてのテンプレート駆動フォーム機能にアクセスできます。
> 1. `HeroFormComponent`を`@NgModule`デコレータで定義された宣言のリストに追加します。 これにより、このモジュール全体で`HeroFormComponent`コンポーネントが表示されます。

　

> コンポーネント、ディレクティブ、またはパイプがimports配列のモジュールに属している場合は、宣言配列でそれを再宣言しないでください。
> もしあなたがそれを書き、それがこのモジュールに属していれば、それを宣言配列で宣言してください。

## app.component.tsを修正する

`AppComponent`はアプリケーションのルートコンポーネントです。 新しい`HeroFormComponent`をホストします。

「QuickStart」バージョンの内容を次のものに置き換えます。

*src/app/app.component.ts*

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

@Component({
  selector: 'my-app',
  template: '<hero-form></hero-form>'
})
export class AppComponent { }
```

変更は2つだけです。 `template`は、単にコンポーネントの`selector`プロパティで識別される新しい要素タグです。これは、アプリケーションコンポーネントがロードされたときにヒーローフォームを表示します。またクラス本体から`name`フィールドを削除しました。


## HTMLフォームテンプレートの初期セットアップ

次の内容のテンプレートファイルを作成します。

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

```
<div class="container">
    <h1>Hero Form</h1>
    <form>
      <div class="form-group">
        <label for="name">Name</label>
        <input type="text" class="form-control" id="name" required>
      </div>

      <div class="form-group">
        <label for="alterEgo">Alter Ego</label>
        <input type="text" class="form-control" id="alterEgo">
      </div>

      <button type="submit" class="btn btn-success">Submit</button>

    </form>
</div>
```

言語は単にHTML5です。 ヒーローフィールドの2つを表示しています。名前とalterEgoを入力ボックスに入力するために開きます。

Name `<input>` コントロールにはHTML5の `required` 属性を記述します｡`alterEgo`はオプションであるため、Alter Ego `<input>` コントロールには`required` 属性は適用しません。

下部に[送信]ボタンを追加して、スタイリングのためにいくつかのクラスを追加しました。

Angular固有の機能はまだ使用していません。バインディングや追加の指示はなく、レイアウトだけです。

> テンプレート駆動フォームでは、FormsModuleをインポートした場合、FormsModuleを使用するために `<form>` タグに何もする必要はありません。それがどのように機能するかを確認してください。

`container`、`form-group`、`form-control`、および `btn` のクラスは、Twitter Bootstrapに由来します。 これらのクラスは純粋なお化粧です。 ブートストラップはフォームに小さなスタイルを与えます。

> Angular フォームはスタイルライブラリを必要としません
> 
> Angularは、コンテナ、フォームグループ、フォームコントロール、btnクラス、または外部ライブラリのスタイルを使用しません。 AngularアプリはCSSライブラリを使用することも、まったく使用しないこともできます。

スタイルシートを追加するには、index.htmlを開き、次のリンクを`<head>`に追加します。

*src/index.html (bootstrap)*

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

## *ngFor で power を加える

heroは、政府機関が承認した権限のリストから1つの超大国を選ぶ必要があります。 あなたはそのリストを内部的に（`HeroFormComponent`の中で）管理しています｡

フォームに `select` を追加し、以前は「[Displaying Data](https://angular.io/guide/displaying-data)」ページで表示されていた手法である`ngFor`を使用して、オプションを`powers`リストにバインドします。

*Alter Ego*グループのすぐ下に次のHTMLを追加します。

*src/app/hero-form.component.html (powers)*

```
<div class="form-group">
  <label for="power">Hero Power</label>
  <select class="form-control" id="power" required>
    <option *ngFor="let pow of powers" [value]="pow">{{pow}}</option>
  </select>
</div>
```

このコードは、powersリスト内の各項目に対して `<option>` タグを繰り返します。`pow`テンプレートの入力変数は、interpolation syntax を用いて名前を表示することで、繰り返す度にで異なる出力になっています｡

## ngModelによる双方向データバインディング

このまますぐにアプリケーションを実行すると、残念なことが起きます。

![Early form with no binding](https://angular.io/generated/images/guide/forms/hero-form-3.png)

まだ`Hero`がバインディングされていないので、ヒーローデータは表示されません。 以前のページからそれを行う方法を知っています。 データの表示はプロパティのバインディングを教えます。 ユーザー入力は、イベントバインディングを使用してDOMイベントをリスンする方法と、表示された値でコンポーネントプロパティを更新する方法を示します。

今度は、同時に表示、聞いて、抽出する必要があります。

すでに知っているテクニックを使用することもできますが、新しい`[(ngModel)]`構文を使用すると、フォームをモデルに簡単にバインドすることができます。

Nameの`<input>`タグを見つけて、次のように更新します。

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

```
<input type="text" class="form-control" id="name"
       required
       [(ngModel)]="model.name" name="name">
TODO: remove this: {{model.name}}
```

> input タグの後に確認用のinterpolationを追加したので、何をしているのかを見ることができます。動作確認ができたらこの記述を削除するようにTODOメモを残しています｡

バインディング構文に注目してください：`[(ngModel)]="..."` データを表示するにはさらに1つの追加が必要です。フォームのテンプレート変数を宣言します。次のように、<form>タグを `#heroForm="ngForm"` で更新します。

*src/app/hero-form.component.html (excerpt)*

```
<form #heroForm="ngForm">
```

変数`heroForm`は、フォーム全体を管理する`NgForm`ディレクティブへの参照になりました。

> ### NgForm ディレクティブ
> 
> NgFormディレクティブとは何ですか？ あなたはNgFormディレクティブを追加しませんでした。
> 
> Angularがそうしました。Angularは自動的にNgFormディレクティブを作成して<form>タグに添付します。
> 
> NgFormディレクティブは、フォーム要素に追加機能を追加します。 ngModelディレクティブとname属性を使用して要素用に作成したコントロールを保持し、その有効性を含めてプロパティを監視します。
> また、それ自身の有効なプロパティもあります。これは、含まれているすべてのコントロールが有効な場合にのみtrueです。

今すぐアプリケーションを実行して、名前の入力ボックスへ入力を開始し、文字の追加と削除を行うと、補間されたテキストが表示されて消えてしまいます。 ある時点では、次のようになります。

![ngModel in action](https://angular.io/generated/images/guide/forms/ng-model-in-action.png)

診断は、値が実際に入力ボックスからモデルに流れて戻ってくるという証拠です。

> これは、双方向のデータバインディングです。詳細については、「[テンプレート構文](https://angular.io/guide/template-syntax)」ページの「[NgModelによる双方向バインディング](https://angular.io/guide/template-syntax#ngModel)」を参照してください。

また、`<input>`タグにname属性を追加し、それを "name" に設定することに注意してください。これはヒーローの名前に意味があります。 一意の値はすべて行いますが、わかりやすい名前を使用すると便利です。 `[(ngModel])` をフォームと組み合わせて使用する場合、`name`属性を定義する必要があります。

> 内部的には、AngularはFormControlインスタンスを作成し、<form>タグにAngularを付けたNgFormディレクティブを登録します。 各FormControlは、name属性に割り当てた名前で登録されます。 前のセクション、The NgFormディレクティブを読んでください。

同様の`[(ngModel)]`バインディングと名前属性を*Alter Ego*と*Hero Power*に追加します。 入力ボックスのバインディングメッセージを破棄し、コンポーネントの診断プロパティに新しいバインディング（上部）を追加します。 その後、ヒーローモデル全体に対して双方向データバインディングが機能することを確認できます。

修正後、フォームのコアは次のようになります。

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

```
{{diagnostic}}
<div class="form-group">
  <label for="name">Name</label>
  <input type="text" class="form-control" id="name"
         required
         [(ngModel)]="model.name" name="name">
</div>

<div class="form-group">
  <label for="alterEgo">Alter Ego</label>
  <input type="text"  class="form-control" id="alterEgo"
         [(ngModel)]="model.alterEgo" name="alterEgo">
</div>

<div class="form-group">
  <label for="power">Hero Power</label>
  <select class="form-control"  id="power"
          required
          [(ngModel)]="model.power" name="power">
    <option *ngFor="let pow of powers" [value]="pow">{{pow}}</option>
  </select>
</div>
```

> - 各input要素にはid属性があり、label要素のfor属性でそのラベルを入力コントロールと照合するために使用されます。
> - 各入力要素には、フォームにコントロールを登録するためにAngularフォームで必要なnameプロパティがあります。

今すぐあなたのアプリケーションを実行し、すべてのヒーローモデルのプロパティを変更すると、フォームは次のように表示されることがあります：

![ngModel in action](https://angular.io/generated/images/guide/forms/ng-model-in-action-2.png)

フォームの上部付近の診断によって、すべての変更がモデルに反映されていることが確認されます。
`{{diagnostic}}` のバインディングを削除します。

## ngModelを使用して制御状態と有効性を追跡する
フォーム内でngModelを使用すると、単なる双方向データバインディング以上のことができます。 また、ユーザーがコントロールにタッチしたか、値が変更されたか、または値が無効になったかどうかが示されます。

NgModelディレクティブは状態を追跡するだけではありません。 状態を反映する特殊なAngular CSSクラスでコントロールを更新します。 これらのクラス名を利用して、コントロールの外観を変更することができます。

State	Class if true	Class if false
The control has been visited.	ng-touched	ng-untouched
The control's value has changed.	ng-dirty	ng-pristine
The control's value is valid.	ng-valid	ng-invalid

| State | true時に付与されるclass | false時に付与されるclass  |
| ---- | ---- | ---- |
| コントロールが操作された | `ng-touched` | `ng-untouched` |
| コントロールの値が変更された | `ng-dirty` | `ng-pristine` |
| コントロールの値がvalidである | `ng-valid` | `ng-invalid` |

名前 `<input>` タグに一時的にspyという名前のテンプレート参照変数を追加し、それを使用して入力のCSSクラスを表示します。

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

```
<input type="text" class="form-control" id="name"
  required
  [(ngModel)]="model.name" name="name"
  #spy>
<br>TODO: remove this: {{spy.className}}
```

今すぐアプリケーションを実行し、名前の入力ボックスを見てください。 次の手順を正確に実行してください。

1. 見て、触れないでください。
1. 名前ボックスの内側をクリックし、外側をクリックします。
1. 名前の最後にスラッシュを追加します。
1. 名前を消去します。

アクションと効果は次のとおりです。

![Control State Transition](https://angular.io/generated/images/guide/forms/control-state-transitions-anim.gif)

次の遷移とクラス名が表示されます。

![Control state transitions](https://angular.io/generated/images/guide/forms/ng-control-class-changes.png)

`ng-valid` / `ng-invalid` ペアは、値が無効な場合に強いビジュアル信号を送信したいので、最も興味深いものです。 また、必須フィールドに印を付ける必要があります。 このような視覚的フィードバックを作成するには、`ng-*` CSSクラスの定義を追加します。

`#spy` テンプレート参照変数とTODOコメントを削除します。

## 視覚的なフィードバックのためにカスタムCSSを追加する

入力ボックスの左側にある色付きのバーで、必須フィールドと無効なデータを同時にマークすることができます。

![Invalid Form](https://angular.io/generated/images/guide/forms/validity-required-indicator.png)

この効果は、これらのクラス定義を新しいforms.cssファイルに追加することによって達成されます。このファイルは、プロジェクトにindex.htmlの兄弟として追加します。

*src/forms.css*

```
.ng-valid[required], .ng-valid.required  {
  border-left: 5px solid #42A948; /* green */
}

.ng-invalid:not(form)  {
  border-left: 5px solid #a94442; /* red */
}
```

このスタイルシートを含めるにはindex.htmlの`<head>`をアップデートしてください：

```
<link rel="stylesheet" href="styles.css">
<link rel="stylesheet" href="forms.css">
```

## バリデーションエラーメッセージの表示/非表示

フォームを改善することができます。 [名前]入力ボックスは必須で、これをオフにすると赤いバーが表示されます。 それは何かが間違っていると言いますが、ユーザーは何が間違っているのか、何をすべきかは分かりません。 コントロールの状態を利用して役立つメッセージを表示します。

ユーザーが名前を削除すると、フォームは次のようになります。

![Name required](https://angular.io/generated/images/guide/forms/name-required-error.png)

この効果を得るには、`<input>`タグを次のように拡張します。

テンプレート参照変数。
近くの`<div>`に "必須です"というメッセージが表示されます。このメッセージは、コントロールが無効な場合にのみ表示されます。
次に、名前入力ボックスに追加されたエラーメッセージの例を示します。

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

```
<label for="name">Name</label>
<input type="text" class="form-control" id="name"
       required
       [(ngModel)]="model.name" name="name"
       #name="ngModel">
<div [hidden]="name.valid || name.pristine"
     class="alert alert-danger">
  Name is required
</div>
```

入力ボックスにアクセスするにはテンプレート参照変数が必要ですテンプレート内からの角度コントロール。 ここではnameという名前の変数を作成し、それに "ngModel"という値を与えました。

> なぜ "ngModel"ですか？ ディレクティブのexportAsプロパティは、参照変数をディレクティブにリンクする方法をAngularに通知します。 ngModelディレクティブのexportAsプロパティが "ngModel"であるため、名前をngModelに設定します。

名前コントロールのプロパティをメッセージの`<div>`要素の`hidden`プロパティにバインドすることにより、名前エラーメッセージの表示を制御します。

*src/app/hero-form.component.html (hidden-error-msg)*

```
<div [hidden]="name.valid || name.pristine"
     class="alert alert-danger">
```

この例では、コントロールが有効または元の状態のときにメッセージを非表示にします。 「原始」とは、ユーザーがこのフォームで表示されてから値を変更していないことを意味します。

このユーザーエクスペリエンスは開発者の選択です。いくつかの開発者はメッセージを常に表示することを望んでいます。初期状態を無視すると、値が有効な場合にのみメッセージを非表示にします。新しい（空白の）ヒーローまたは無効なヒーローでこのコンポーネントに着いたら、何かをする前にすぐにエラーメッセージが表示されます。

一部の開発者は、ユーザーが無効な変更を行った場合にのみ、メッセージを表示することを望みます。コントロールが「元気」である間にメッセージを非表示にすると、その目標が達成されます。フォームに新しいヒーローを追加すると、この選択の重要性がわかります。

ヒーローアルターエゴはオプションですので、あなたはそれを残すことができます。

ヒーローパワーの選択が必要です。必要に応じて、同じ種類のエラー処理を`<select>`に追加できますが、選択ボックスではすでに有効な値に制限されているため、必須ではありません。

これで新しいヒーローをこのフォームに追加します。新しいヒーローボタンをフォームの下部に配置し、そのクリックイベントを`newHero`コンポーネントメソッドにバインドします。


*src/app/hero-form.component.html (New Hero button)*

```
<button type="button" class="btn btn-default" (click)="newHero()">New Hero</button>
```

*src/app/hero-form.component.ts (New Hero method)*

```
newHero() {
  this.model = new Hero(42, '', '');
}
```

アプリケーションをもう一度実行し、New Heroボタンをクリックすると、フォームがクリアされます。 入力ボックスの左側に必要なバーは赤で、無効な名前と電源のプロパティを示します。 これは必須フィールドなので理解できます。 フォームが初期状態であるため、エラーメッセージは表示されません。 あなたはまだ何も変えていない。

名前を入力し、New Heroをもう一度クリックします。 アプリケーションには、名前が必要ですエラーメッセージが表示されます。 新しい（空の）ヒーローを作成すると、エラーメッセージは表示されません。 なぜあなたは今、1つを手に入れていますか？

ブラウザツールで要素を調べると、名前の入力ボックスが元の状態になっていないことがわかります。 フォームは、New Heroをクリックする前に名前を入力したことを記憶しています。 ヒーローオブジェクトを置き換えても、フォームコントロールの元の状態は復元されませんでした。

あなたはすべてのフラグを無条件にクリアする必要があります。これは、`newHero()`メソッドを呼び出した後にフォームの`reset()`メソッドを呼び出すことで実行できます。

*src/app/hero-form.component.html (Reset the form)*

```
<button type="button" class="btn btn-default" (click)="newHero(); heroForm.reset()">New Hero</button>
```

「New Hero」をクリックすると、フォームとコントロールフラグの両方がリセットされます。

## ngSubmit でフォームをsubmitする

フォームの下部にある[Submit]ボタンは、単独では何も行いませんが、タイプ`(type="submit")` のためにフォーム送信がトリガーされます。

現時点では、「フォームのsubmit」は役に立ちません。これを便利にするには、フォームのngSubmitイベントプロパティをheroフォームコンポーネントのonSubmit()メソッドにバインドします。

*src/app/hero-form.component.html (ngSubmit)*

```
<form (ngSubmit)="onSubmit()" #heroForm="ngForm">
```

テンプレート参照変数、#heroFormを既に定義しておき、それを値 "ngForm"で初期化しました。 さて、この変数を使用して、Submitボタンでフォームにアクセスします。

フォームの全体的な有効性は、イベントバインディングを使用してheroForm変数を介してボタンのdisabledプロパティにバインドします。 コードは次のとおりです：

*src/app/hero-form.component.html (submit-button)*

```
<button type="submit" class="btn btn-success" [disabled]="!heroForm.form.valid">Submit</button>
```

今すぐアプリケーションを実行すると、ボタンが有効になっていることがわかりますが、まだ便利な機能はありません。

ここで名前を削除すると、エラーメッセージに正しく記されている「必須」ルールに違反します。 [送信]ボタンも無効になっています。

感心しない？ それについて少し考えてみてください。 あなたはAngularの助けを借りずにボタンの有効/無効状態をフォームの有効性に結びつけるために何かする必要がありますか？

それはこれほど簡単でした：

1. （拡張された）フォーム要素にテンプレート参照変数を定義します。
1. 多くの行のボタンの変数を参照してください。

## 2つのフォーム領域を切り替える（extra credit）

フォームをsubmitするのは現時点ではドラマチックはありません。

> デモのための驚くべき観察。 正直言って、それを怒らせても、あなたは新しい形について何も教えてくれません。 しかし、これはあなたの新たに獲得した拘束力のあるスキルのいくつかを行使する機会です。
> もし興味がなければ、このページのまとめにスキップしてください。

より目立つような視覚効果を得るには、データ入力領域を非表示にして別のものを表示します。

フォームを<div>にラップし、隠されたプロパティをHeroFormComponent.submittedプロパティにバインドします。

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

```
<div [hidden]="submitted">
  <h1>Hero Form</h1>
  <form (ngSubmit)="onSubmit()" #heroForm="ngForm">

     <!-- ... all of the form ... -->

  </form>
</div>
```

メインフォームは最初から表示されます。なぜなら、HeroFormComponentのこのフラグメントが示すように、フォームを送信するまで、サブミットされたプロパティはfalseであるからです。

*src/app/hero-form.component.ts (submitted)*

```
submitted = false;

onSubmit() { this.submitted = true; }
```

[送信]ボタンをクリックすると、`submitted`フラグが`true`になり、フォームは計画どおりに消えます。

フォームが提出された状態になっている間、アプリは別のものを表示する必要があります。 作成した`<div>`ラッパーの下に次のHTMLを追加します。

*src/app/hero-form.component.html (excerpt)*

```
<div [hidden]="!submitted">
  <h2>You submitted the following:</h2>
  <div class="row">
    <div class="col-xs-3">Name</div>
    <div class="col-xs-9  pull-left">{{ model.name }}</div>
  </div>
  <div class="row">
    <div class="col-xs-3">Alter Ego</div>
    <div class="col-xs-9 pull-left">{{ model.alterEgo }}</div>
  </div>
  <div class="row">
    <div class="col-xs-3">Power</div>
    <div class="col-xs-9 pull-left">{{ model.power }}</div>
  </div>
  <br>
  <button class="btn btn-primary" (click)="submitted=false">Edit</button>
</div>
```

ヒーローが再びあり、補間バインディングで読み取り専用で表示されます。 この`<div>`は、コンポーネントがサブミットされた状態のときにのみ表示されます。

HTMLには、クリックイベントが送信済みフラグをクリアする式にバインドされた編集ボタンが含まれています。

編集ボタンをクリックすると、このブロックは消え、編集可能なフォームが再び表示されます。

## まとめ

このページで説明するAngularフォームは、データの変更、検証などをサポートするために、次のフレームワーク機能を利用しています。

- Angular HTMLフォームテンプレート。
- `@Component` デコレータを持つフォームコンポーネントクラス。
- NgForm.ngSubmitイベントプロパティにバインドしてフォームの送信を処理します。
- `#heroForm` や `#name` などのテンプレート参照変数。
- [（ngModel）]構文は、双方向データバインディング用です。
- 検証およびフォーム要素の変更追跡にname属性を使用する。
- コントロールが有効かどうかをチェックし、エラーメッセージを表示/非表示にするための入力コントロールの参照変数の有効なプロパティ。
- NgFormの有効性にバインドすることによって、送信ボタンの有効状態を制御します。
- 無効なコントロールについてユーザーに視覚的なフィードバックを提供するカスタムCSSクラス。

最終的なプロジェクトのフォルダ構造は次のようになります。

> - angular-forms
>  - src
>    - app
>      - app.component.ts
>      - app.module.ts
>      - hero.ts
>      - hero-form.component.html
>      - hero-form.component.ts
>    - main.ts
>    - tsconfig.json
>    - index.html
>  - node_modules ...
>  - package.json

アプリケーションの最終バージョンのコードは次のとおりです。

[（省略）](https://angular.io/guide/forms#conclusion)