Skip to content

Instantly share code, notes, and snippets.

@dolpen
Last active April 21, 2016 07:58
Show Gist options
  • Save dolpen/f1a1fa368f1c534b4a9c7e0342fa0119 to your computer and use it in GitHub Desktop.
Save dolpen/f1a1fa368f1c534b4a9c7e0342fa0119 to your computer and use it in GitHub Desktop.

ヒーローの情報を編集する画面

今回は、ヒーローの情報を編集する簡単なエディタを作る。

前回までのあらすじ

あらゆる物語にはスタート地点がある。 今回の話は クイックスタート が終わったところから始めよう。

今回作るもののデモ

angular2-tour-of-heroes という名前でフォルダを作り、クイックスタートと同じ手順を繰り返し、 アプリケーションを作っていくためのフォルダ構造を作ろう。

あるいは、クイックスタート終了時の全ソースコードをダウンロードして始めることもできる。

下記のような構造になっていればよい。

angular2-tour-of-heroes
├app
│├app.component.ts
│└main.ts
├node_modules ...
├typings ...
├index.html
├package.json
├styles.css
├tsconfig.json
└typings.json

npm start で TypeScript の自動コンパイルとアプリケーションのリロードを有効にしておこう。 このコマンドは TypeScript のコンパイラを watch mode で動かし、サーバーを動作させる。 アプリケーションをブラウザで起動し、開発中にアプリケーションを動作させたまま更新を反映させることができる。

ヒーローを表示する

ヒーローの情報をアプリケーションに表示したい。

AppComponent に2つのプロパティを追加しよう。 title プロパティはこのアプリケーションの名前、 そして hero プロパティは「Windstorm」という名前のヒーローのことだ。

export class AppComponent {
    title = 'Tour of Heroes';
    hero = 'Windstorm';
}

そして、 @Component 内の(HTMLの)テンプレートを、新しいプロパティをバインディングするように書き換える。

template: '<h1>{{title}}</h1><h2>{{hero}} details!</h2>'

反映したら、ブラウザは更新され、タイトルとヒーローの情報が表示されるだろう。

{{title}}{{hero}} は、コンポーネントのプロパティから値を読み出し、それを表示せよ、というアプリケーションへの指示を示している。 つまりこれは、 片方向データバインディング(one-way data binding) によるデータの 補完(interpolation) である。

この補完については、データの表示の章で、より深く学べるだろう。

ヒーローの情報をオブジェクトにする

今のところ、ヒーローの情報は名前を示す文字列でしかない。 もっとたくさんのプロパティがこの先必要になってくる。 そこで、ヒーローの情報を単なる文字列から クラス(Class) に変えてみよう。

idname というプロパティを持つ Hero というクラスを作ってみる。 app.component.ts の上部、import 宣言のすぐ下に書き加えてみよう。

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

これでヒーローを示すクラスができたので、コンポーネントの hero プロパティを Hero 型に直してみよう。 id は 1 で、name は「Windstorm」だ。

hero: Hero = {
    id: 1,
    name: 'Windstorm'
};

ヒーローの情報を文字列からオブジェクトに変えてしまったので、今度はテンプレートも、オブジェクトの中の name プロパティを参照するように変更する必要がある。

template: '<h1>{{title}}</h1><h2>{{hero.name}} details!</h2>'

反映したら、ブラウザは更新され、ヒーローの名前が正しく表示されるだろう。

HTMLを追加する

名前はしっかり表示できた。しかし、ヒーローの情報をすべて表示したい。 <div> を使って、ヒーローの ID と名前をそれぞれ別枠で表示しよう。

template: '<h1>{{title}}</h1><h2>{{hero.name}} details!</h2><div><label>id: </label>{{hero.id}}</div><div><label>name: </label>{{hero.name}}</div>'

ああ…とても長い文字列になってしまった。テンプレートの編集時にミスをしないように、よりよい形にしてみよう。

テンプレートを複数行で指定する

文字列を連結することでより長いテンプレートを作ることができ、それを読むことは不可能ではないだろう。 しかしおそらく醜く、読みづらく、編集で構文エラーを混ぜ込みやすいものになる。 そこで、 ES2015 と TypeScript のテンプレート文字列用構文を使い、後で発狂してしまわないようにメンテナンスしてみよう。 今シングルクォートで囲っている文字列をバッククォートで囲むようにして、 <h1><h2><div> でそれぞれ改行してみよう。

template:`
  <h1>{{title}}</h1>
  <h2>{{hero.name}} details!</h2>
  <div><label>id: </label>{{hero.id}}</div>
  <div><label>name: </label>{{hero.name}}</div>
  `

ヒーローの情報を編集する

ヒーローの名前をテキストフィールドにして、編集できるようにしたい。 <label> の次にあるヒーローの名前を、 <input> を使って以下のように書き換えてみよう。

template:`
  <h1>{{title}}</h1>
  <h2>{{hero.name}} details!</h2>
  <div><label>id: </label>{{hero.id}}</div>
  <div>
    <label>name: </label>
    <input value="{{hero.name}}" placeholder="name">
  </div>
  `

これでヒーローの名前が <input> のテキストフィールドで表示されるようになった。 しかし何かがおかしい。 名前を書き換えたとき、それが <h2> の中身には反映されていないのだ。 <input> への片方向バインディングでは、そのような動作をさせることはできない。

双方向データバインディング

これから <input> フィールドにヒーローの名前を表示し、それを編集し、 編集した内容が、ヒーローの名前を表示するあらゆる場所に反映されるようにする。 つまり、これは 双方向データバインディング(two-way data binding) をする、ということだ。

テンプレートを ngModel という双方向データバインディングのための基本ディレクティブを使うように書き換えてみよう。

ngModel については、フォームおよびテンプレート構文の章で、より深く学べるだろう。

<input> の部分を書き換えよう。

<input [(ngModel)]="hero.name" placeholder="name">

反映したら、ブラウザは更新され、表示された名前を書き換えたときに <h2> に即座に反映されるだろう。

今回のまとめ

今回作ったものを整理してみよう。

  • {{...}} という記法によるデータの補完で、アプリケーションのタイトルとヒーローのオブジェクトのプロパティを表示した。
  • ES2015形式のテンプレート記法でテンプレートを読みやすくした。
  • <input>ngModel ディレクティブを使うことにより、ヒーローの名前を編集可能にした。ngModel ディレクティブは変更内容を別の部分の表示に伝播させた。

今回作ったもののデモ

最終的なapp.component.tsはこのようになっているはずだ。

import {Component} from 'angular2/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'
 };
}

次回

今回作ったアプリケーションでは、一人のヒーローしか表示していなが、本当はたくさんいるヒーローを一覧したい。 また、それらのヒーローの中から一人を選択して情報を表示したい。 次回は、そのような一覧を検索したり、テンプレートに情報を補完したり、選択できるようにする方法を学んでいく。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment