mac OSX El Capitan Sierra で Angular 2 入門 (チュートリアル体験)　2

#[MASTER/DETAIL](https://angular.io/docs/ts/latest/tutorial/toh-pt2.html)

次のステップに進む

*いい加減な訳`もうちょっとヒーロー欲しいよね。リスト化して自分でヒーロー確認できるようにしようぜ`

はい

まずは下記を`app.component.ts`に追加(export class Heroの下あたりに)

```ts:app.component.ts
・・・・・・・・・・
export class Hero {
  id: number;
  name: string;
}

// 追加(hero array)
const HEROES: Hero[] = [
  { id: 11, name: 'Mr. Nice' },
  { id: 12, name: 'Narco' },
  { id: 13, name: 'Bombasto' },
  { id: 14, name: 'Celeritas' },
  { id: 15, name: 'Magneta' },
  { id: 16, name: 'RubberMan' },
  { id: 17, name: 'Dynama' },
  { id: 18, name: 'Dr IQ' },
  { id: 19, name: 'Magma' },
  { id: 20, name: 'Tornado' }
];
```

`hero: Hero = {・・・}`だったところを修正

```ts:app.component.ts
heroes = HEROES;
```

この辺りで`TypeScript`でだったらこんな風に描けるぜ的なこと言ってる？のかな

template(HTML部分)を編集

```ts:app.component.ts
<h2>My Heroes</h2>
<ul class="heroes">
  <li>
    <!-- each hero goes here -->
  </li>
</ul>
```

ここまでくるとheros配列を使いたい。liのとこでループで回せたらいいよねという話。
そこで使うのが`*ngFor`

```ts:app.component.ts
<li *ngFor="let hero of heroes"></li>
```

`ngFor`の前のアスタリスク(*)がこのシンタックスでは重要な部分だよ！だそうである
詳しくは[Template Syntax](https://angular.io/docs/ts/latest/guide/template-syntax.html#!#ngFor)の章を参照するといいよ。

でもって、`*ngFor="let hero of heroes"`を使うとその中でループ処理を行ってhero classを利用できるようである。

```ts:app.component.ts
<li *ngFor="let hero of heroes">
  <span class="badge">{{hero.id}}</span> {{hero.name}}
</li>
```

これでブラウザをリフレッシュして確認してみると良い。
と言いつつ下記のような`template`の表記をしていたのでこの段階では私は表示されなかった。

```ts:app.component.ts
template: `
    <h1>{{title}}</h1>
    <h2>My Heroes</h2>
    <ul class="heroes">
      <li *ngFor="let hero of heroes">
        <span class="badge">{{hero.id}}</span> {{hero.name}}
      </li>
    </ul>
    <div>
      <label>name: </label>
      <input [(ngModel)]="hero.name" placeholder="name">
    </div>
    `
```

多分これが原因かなと思って下記のようにしたら動いた


```ts:app.component.ts
template: `
    <h1>{{title}}</h1>
    <h2>My Heroes</h2>
    <ul class="heroes">
      <li *ngFor="let hero of heroes">
        <span class="badge">{{hero.id}}</span> {{hero.name}}
      </li>
    </ul>
    `
```

とりあえずこれでヒーローリストは見れるようになった。

#スタイルの追加

`@component`の部分に`styles`を追加

```ts:app.component.ts
styles: [`
  .selected {
    background-color: #CFD8DC !important;
    color: white;
  }
  .heroes {
    margin: 0 0 2em 0;
    list-style-type: none;
    padding: 0;
    width: 15em;
  }
  .heroes li {
    cursor: pointer;
    position: relative;
    left: 0;
    background-color: #EEE;
    margin: .5em;
    padding: .3em 0;
    height: 1.6em;
    border-radius: 4px;
  }
  .heroes li.selected:hover {
    background-color: #BBD8DC !important;
    color: white;
  }
  .heroes li:hover {
    color: #607D8B;
    background-color: #DDD;
    left: .1em;
  }
  .heroes .text {
    position: relative;
    top: -3px;
  }
  .heroes .badge {
    display: inline-block;
    font-size: small;
    color: white;
    padding: 0.8em 0.7em 0 0.7em;
    background-color: #607D8B;
    line-height: 1em;
    position: relative;
    left: -1px;
    top: -4px;
    height: 1.8em;
    margin-right: .8em;
    border-radius: 4px 0 0 4px;
  }
`]
```

別の章で別個にCSS定義するのはやるけど今はインラインで我慢してね？っていうてますかね
さて、スタイルを追加したのでもう一度localhost:3000を見ると・・・

![スクリーンショット 2016-12-21 2.44.20.png](https://qiita-image-store.s3.amazonaws.com/0/97116/16a35c28-6f5b-0e29-23fc-a097ce777a5c.png)

おお、綺麗になってますね。

#クリックイベントの追加

`li`を変更してAngularのクリックイベントをつけます。

```ts:app.component.ts
<li *ngFor="let hero of heroes" (click)="onSelect(hero)">
  <span class="badge">{{hero.id}}</span> {{hero.name}}
</li>
```

なんかここで追加した`onSelect`について実装はとりあえず置いといてどういう動きしたらいいかを考えようぜって言ってるのかな？
選択したヒーローをcomponentにsetしたいからそれ用の変数を作ろう。

`export class AppComponent`に選択したヒーロー格納用のproperty`selectedHero`を追加

```ts:app.component.ts
selectedHero： Hero;
```

さらにイベントで呼び出している`onSelect`も追加

```ts:app.component.ts
onSelect(hero: Hero): void {
  this.selectedHero = hero;
}
```

`template`に選択した値を表示するHTML(?)を追加

```ts:app.component.ts
<h2>{{selectedHero.name}} details!</h2>
<div><label>id: </label>{{selectedHero.id}}</div>
<div>
    <label>name: </label>
    <input [(ngModel)]="selectedHero.name" placeholder="name"/>
</div>
```

これでヒーローをクリックするとしたの方に該当のデータが表示されるようになると思いきやならない

*ちなみに私は下記の前にさらに別のエラーが出た。`EXCEPTION: TypeError: Cannot set property 'message' of undefined`である。これは[ここ](http://stackoverflow.com/questions/41241477/angular2-typeerror-cannot-set-property-name-of-undefined)を参照した。packageの問題だったようで`zone.js`のインストールで解決した。

#ngIfの利用
おそらくこんなエラーがブラウザのコンソールに表示されているのではないだろうか

```
EXCEPTION: TypeError: Cannot read property 'name' of undefined in [null]
```

初期値は空だから参照しようとするとエラーが出るよねという当たり前の話。
なのでif文みたいなのがあると便利だね。

あるよ！

```ts:app.component.ts
<div *ngIf="selectedHero">
  <h2>{{selectedHero.name}} details!</h2>
  <div><label>id: </label>{{selectedHero.id}}</div>
  <div>
    <label>name: </label>
    <input [(ngModel)]="selectedHero.name" placeholder="name"/>
  </div>
</div>
```

ここでもアスタリスクは重要だからちゃんとつけてねって言われた・・・。

さて、これでlocalhost:3000をみてみると・・・
![スクリーンショット 2016-12-21 3.16.11.png](https://qiita-image-store.s3.amazonaws.com/0/97116/ca87c755-ad43-bdfe-034f-aee660a346d1.png)

クリックしてみると・・・
![スクリーンショット 2016-12-21 3.17.03.png](https://qiita-image-store.s3.amazonaws.com/0/97116/329e1cac-82fa-e117-6b28-e241e6ca375a.png)

表示された。

あとは選択されたヒーローにcssクラスを追加したい（選択されたことを明示的にしたい）ので下記を追加。

```ts:app.component.ts
[class.selected]="hero === selectedHero"
```

追加されたtemplateはしたみたいな感じ。

```ts:app.component.ts
<li *ngFor="let hero of heroes"
  [class.selected]="hero === selectedHero"
  (click)="onSelect(hero)">
  <span class="badge">{{hero.id}}</span> {{hero.name}}
</li>
```

これでこのステップは終了！

今回編集ファイルは一個だけ(app.component.ts)だったね。

最終的には下記ができてれば問題ない。


```ts:app.component.ts
import { Component } from '@angular/core';
export class Hero {
  id: number;
  name: string;
}
const HEROES: Hero[] = [
  { id: 11, name: 'Mr. Nice' },
  { id: 12, name: 'Narco' },
  { id: 13, name: 'Bombasto' },
  { id: 14, name: 'Celeritas' },
  { id: 15, name: 'Magneta' },
  { id: 16, name: 'RubberMan' },
  { id: 17, name: 'Dynama' },
  { id: 18, name: 'Dr IQ' },
  { id: 19, name: 'Magma' },
  { id: 20, name: 'Tornado' }
];
@Component({
  selector: 'my-app',
  template: `
    <h1>{{title}}</h1>
    <h2>My Heroes</h2>
    <ul class="heroes">
      <li *ngFor="let hero of heroes"
        [class.selected]="hero === selectedHero"
        (click)="onSelect(hero)">
        <span class="badge">{{hero.id}}</span> {{hero.name}}
      </li>
    </ul>
    <div *ngIf="selectedHero">
      <h2>{{selectedHero.name}} details!</h2>
      <div><label>id: </label>{{selectedHero.id}}</div>
      <div>
        <label>name: </label>
        <input [(ngModel)]="selectedHero.name" placeholder="name"/>
      </div>
    </div>
  `,
  styles: [`
    .selected {
      background-color: #CFD8DC !important;
      color: white;
    }
    .heroes {
      margin: 0 0 2em 0;
      list-style-type: none;
      padding: 0;
      width: 15em;
    }
    .heroes li {
      cursor: pointer;
      position: relative;
      left: 0;
      background-color: #EEE;
      margin: .5em;
      padding: .3em 0;
      height: 1.6em;
      border-radius: 4px;
    }
    .heroes li.selected:hover {
      background-color: #BBD8DC !important;
      color: white;
    }
    .heroes li:hover {
      color: #607D8B;
      background-color: #DDD;
      left: .1em;
    }
    .heroes .text {
      position: relative;
      top: -3px;
    }
    .heroes .badge {
      display: inline-block;
      font-size: small;
      color: white;
      padding: 0.8em 0.7em 0 0.7em;
      background-color: #607D8B;
      line-height: 1em;
      position: relative;
      left: -1px;
      top: -4px;
      height: 1.8em;
      margin-right: .8em;
      border-radius: 4px 0 0 4px;
    }
  `]
})
export class AppComponent {
  title = 'Tour of Heroes';
  heroes = HEROES;
  selectedHero: Hero;
  onSelect(hero: Hero): void {
    this.selectedHero = hero;
  }
}
```

次はマルチコンポーネント！