[和訳] 2. The Hero Editor (Angular公式チュートリアル)

この投稿は、Angular公式チュートリアルの [2. The Hero Editor](https://v4.angular.io/tutorial/toh-pt1) を和訳した記事です。
職場で行うAngular勉強会を円滑に進めることを目的としています。

筆者自身もAngularについては初級者で、英語の知識も乏しいため、記事内容への指摘がありましたら是非コメントをお願いします。

**なお、この記事はAngular v4に対応したチュートリアルの和訳記事です。**
**最新版のチュートリアルではありませんのでご注意ください。**

【チュートリアル一覧】
_1. Introduction_ : [和訳ページ](https://qiita.com/Imamotty/items/75f2974d95acc15359fd) / [原文](https://v4.angular.io/tutorial)
**_2. The Hero Editor_ : このページです / [原文](https://v4.angular.io/tutorial/toh-pt1)**
_3. Master/Detail_ : [和訳ページ](https://qiita.com/Imamotty/items/eac7cdef533ab7cb4152) / [原文](https://v4.angular.io/tutorial/toh-pt2)
_4. Multiple Components_ : [和訳ページ](https://qiita.com/Imamotty/items/796338e1e3224eb9ba34) / [原文](https://v4.angular.io/tutorial/toh-pt3)
_5. Services_ : 和訳ページ作成中 / [原文](https://v4.angular.io/tutorial/toh-pt4)
_6. Routing_ : 和訳ページ作成中 / [原文](https://v4.angular.io/tutorial/toh-pt5)
_7. HTTP_ : 和訳ページ作成中 / [原文](https://v4.angular.io/tutorial/toh-pt6)

***
# The Hero Editor
## ローカルで開発するためのセットアップ
こちらの[設定ガイド](https://v4.angular.io/guide/setup)に従って、`angle-tour-of-heroes`という名前の新しいプロジェクトを作成します。

ファイル構造は次のようになります。

<img width="696" alt="スクリーンショット 2017-10-26 23.51.38.png" src="https://qiita-image-store.s3.amazonaws.com/0/26577/0f1f166d-af5d-d887-c9d1-071e2c700186.png">

このページが完成したら、アプリはこの例のようになります。
https://v4.angular.io/generated/live-examples/toh-pt1/eplnkr.html

## アプリをコンパイル・実行し続ける
ターミナル画面で以下のコマンドを入力します。

```bash
npm start
```

このコマンドは、「watchモード」でTypeScriptコンパイラを実行し、コードが変更されたときに自動的に再コンパイルします。
また、ブラウザでアプリを同時に起動し、コードが変更されたときにブラウザを更新します。

ブラウザを再コンパイルまたは更新するために一時停止することなく、
_Tour of Heroes_ を構築し続けることができます。

## ヒーローを表示する
`AppComponent`に2つのプロパティを追加します。
1. アプリケーション名を値に持つ`title`プロパティ
2. ヒーローの名前として"Windstorm"という値を持つ`hero`プロパティ

```TypeScript:app.component.ts(AppComponent_class)
export class AppComponent {
  title = 'Tour of Heroes';
  hero = 'Windstorm';
}
```

`@Component`デコレータのテンプレートを、
これらの新しいプロパティへのデータバインディングで更新します。

```app.component.ts(@Component)
template: `<h1>{{title}}</h1><h2>{{hero}} details!</h2>`
```

ブラウザが更新され、タイトルとヒーロー名が表示されます。

二重中括弧はAngularの補間バインディング構文(_interpolation_構文)です。 
これらの補間バインディングは、HTMLのh1, h2タグ内に、
`AppComponent`の`title`プロパティと`hero`プロパティの値を文字列として表示します。

> 補間の詳細については、[Displaying Data](https://v4.angular.io/guide/displaying-data)ページを参照してください。

### Heroオブジェクト
ヒーローは更に多くの属性を必要とします。
`hero`プロパティを文字列リテラルからクラスに変換します。

`id`と`name`プロパティを持つ`Hero`クラスを作成します。
これらのプロパティを`app.component.ts`ファイルの上部、importステートメントのすぐ下に追加します。

```TypeScript:src/app/app.component.ts(Hero_class)
export class Hero {
  id: number;
  name: string;
}
```

`AppComponent`クラスでは、コンポーネントの`hero`プロパティが`Hero`型になるようにコンポーネントのリファクタリングを行い、
`id`プロパティを1、`name`プロパティを`Windstorm`で初期化します。

```TypeScript:src/app/app.component.ts(hero_property)
hero: Hero = {
  id: 1,
  name: 'Windstorm'
};
```

`hero`プロパティを文字列からオブジェクトに変更したので、
`hero`の`name`プロパティを参照するようにテンプレートのバインディングを更新します。

```src/app/app.component.ts(template)
template: `<h1>{{title}}</h1><h2>{{hero.name}} details!</h2>`
```

### 複数行のテンプレート文字列でのHTMLの追加
`hero`のすべてのプロパティを表示するには、
`hero.id`プロパティのために`<div>`を追加し、`hero.name`プロパティにもう1つの`<div>`を追加します。 
テンプレートを読みやすく保つために、それぞれの`<div>`を別々の行に配置します。

ES2015とTypeScriptのテンプレートリテラル機能のおかげで、
コンポーネントの`template`をバッククォートで囲むことで、`<h1>`、`<h2>`、および`<div>`要素をそれぞれの行に配置することができます。
詳細については、[Template literals](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals)を参照してください。

```app.component.ts(AppComponent's_template)
template: `
  <h1>{{title}}</h1>
  <h2>{{hero.name}} details!</h2>
  <div><label>id: </label>{{hero.id}}</div>
  <div><label>name: </label>{{hero.name}}</div>
  `
```

## ヒーロー名を編集する
ユーザーは`<input>`テキストボックスでヒーロー名を編集できるはずです。
テキストボックスに`hero.name`プロパティが表示され、ユーザーの入力時にそのプロパティが更新されるようにします。

### 双方向バインディング
templateのヒーロー名をリファクタリングすると、次のようになります。

```src/app/app.component.ts(template)
<div>
  <label>name: </label>
  <input [(ngModel)]="hero.name" placeholder="name">
</div>
```

`[(ngModel)]`は、`hero.name`プロパティをテキストボックスにバインドするAngular構文です。 
データはプロパティからテキストボックス、テキストボックスからプロパティの両方向に流れます。

しかし残念ながら、この変更の直後にアプリケーションが中断します。 
ブラウザのコンソールでは、「`ngModel`...は`input`のプロパティではない」というエラーメッセージをAngularが出力しています。

`NgModel`は有効なAngularディレクティブですが、デフォルトでは使用できません。 
オプションの`FormsModule`に属するため、
`NgModel`を使用するにはそのモジュールの使用を宣言する必要があります。

### FormsModuleをインポート
`app.module.ts`ファイルを開き、`@angular/forms`ライブラリから`FormsModule`シンボルをインポートします。 
その後、`FormsModule`を`@NgModule`メタデータの`imports`配列に追加します。
この配列には、アプリケーションが使用する外部モジュールのリストが含まれています。

```TypeScript:app.module.ts(FormsModule_import)
import { NgModule }      from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule }   from '@angular/forms'; // <-- ここでNgModelを有効化

import { AppComponent }  from './app.component';

@NgModule({
  imports: [
    BrowserModule,
    FormsModule // <-- [(ngModel)]のバインド前にFormsModuleをインポート
  ],
  declarations: [
    AppComponent
  ],
  bootstrap: [ AppComponent ]
})
export class AppModule { }
```

>`FormsModule`と`ngModel`の詳細は、[Forms](https://v4.angular.io/guide/forms)ページの[Two-way data binding with ngModel](https://v4.angular.io/guide/forms#ngModel)や、[Template Syntax](https://v4.angular.io/guide/template-syntax)ページの[Two-way binding with NgModel](https://v4.angular.io/guide/template-syntax#ngModel)を参照してください。

ブラウザが更新されると、アプリは再び動作するはずです。
ヒーローの名前を編集し、テキストボックスの上にある`<h2>`に変更が反映されていることを確認できます。

## まとめ
あなたが作ったものを確認しましょう。

* `Tour of Heroes`アプリは、補間の二重中括弧（一方向データバインディングの一種）を使用して、アプリタイトルと`Hero`オブジェクトのプロパティを表示します。
* ES2015のテンプレートリテラル機能を使用して複数行のテンプレートを作成し、テンプレートを読みやすくしました。
* Angular組み込みの`ngModel`ディレクティブを使用して、`<input>`要素に双方向データバインディングを追加しました。 このバインディングは、ヒーローの名前を表示し、ユーザーがそれを変更できるようにします。
* `ngModel`ディレクティブは、`hero.name`に対する他のすべてのバインディングに変更を伝播します。

あなたのアプリは、今このようになっているでしょう。
https://v4.angular.io/generated/live-examples/toh-pt1/eplnkr.html

`app.component.ts`全体は以下のようになります。

```TypeScript:src/app/app.component.ts
import { Component } from '@angular/core';

export class Hero {
  id: number;
  name: string;
}

@Component({
  selector: 'my-app',
  template: `
    <h1>{{title}}</h1>
    <h2>{{hero.name}} details!</h2>
    <div><label>id: </label>{{hero.id}}</div>
    <div>
      <label>name: </label>
      <input [(ngModel)]="hero.name" placeholder="name">
    </div>
    `
})
export class AppComponent {
  title = 'Tour of Heroes';
  hero: Hero = {
    id: 1,
    name: 'Windstorm'
  };
}
```

## 次のステップ
[次のチュートリアルページ](https://qiita.com/Imamotty/items/eac7cdef533ab7cb4152)では、ヒーローのリストを表示するための`Tour of Heroes`アプリを構築します。
ユーザーはヒーローを選択してその詳細を表示することもできます。 
リストを取得してテンプレートにバインドする方法の詳細を学習します。