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


この投稿は、Angular公式チュートリアルの 2. The Hero Editor を和訳した記事です。
職場で行うAngular勉強会を円滑に進めることを目的としています。

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

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

【チュートリアル一覧】
1. Introduction : 和訳ページ / 原文
2. The Hero Editor : このページです / 原文
3. Master/Detail : 和訳ページ / 原文
4. Multiple Components : 和訳ページ / 原文
5. Services : 和訳ページ作成中 / 原文
6. Routing : 和訳ページ作成中 / 原文
7. HTTP : 和訳ページ作成中 / 原文


The Hero Editor

ローカルで開発するためのセットアップ

こちらの設定ガイドに従って、angle-tour-of-heroesという名前の新しいプロジェクトを作成します。

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

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

アプリをコンパイル・実行し続ける

ターミナル画面で以下のコマンドを入力します。

npm start

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

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

ヒーローを表示する

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

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タグ内に、
AppComponenttitleプロパティとheroプロパティの値を文字列として表示します。

補間の詳細については、Displaying Dataページを参照してください。

Heroオブジェクト

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

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

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

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

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

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

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を参照してください。

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配列に追加します。
この配列には、アプリケーションが使用する外部モジュールのリストが含まれています。

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 { }

FormsModulengModelの詳細は、FormsページのTwo-way data binding with ngModelや、Template SyntaxページのTwo-way binding with 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全体は以下のようになります。

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'
  };
}

次のステップ

次のチュートリアルページでは、ヒーローのリストを表示するためのTour of Heroesアプリを構築します。
ユーザーはヒーローを選択してその詳細を表示することもできます。
リストを取得してテンプレートにバインドする方法の詳細を学習します。