Angular Logo

[Angular]チュートリアルその 4 一覧と詳細のコンポーネントの分割

Angular をチュートリアルを使って勉強する機会があったので、その時の内容について説明していきます。

Angular の本家サイトのチュートリアルの「 Master/Detail Components 」の説明をしていきたいと思います。

今までは Hero コンポーネントだけで一覧の表示と編集を行なっていましたが、それを一覧のコンポーネント( Master )と詳細のコンポーネント(Detail)に分割します。

このチュートリアルがマスターできれば、機能分割されたシンプルなコンポーネントの実装が行えるようになります。

本家サイトはこちらになります。

作成するプロジェクトは「 Tour of Heroes 」というアプリケーションです。

作成するアプリの概要についてはこちらから確認できます。

では、早速始めていきたいと思います!

開発環境

  • macOS : Sierra 10.12.6
  • node : 8.4.0
  • npm : 5.3.0
  • Angular : 4.3.6

HeroDetailComponent の作成

下記コマンドを実行して、 hero-detail コンポーネントを作成します。

$ ng generate component hero-detail

コマンドを実行すると、 HeroDetailComponent が生成され、 AppModule にも宣言情報が追記されます。

テンプレート実装

詳細部分のテンプレートを実装します。

コンポーネントを追加した際に、 hero-detail.component.html というファイルも追加されているので、そのファイルを編集していきます。

<div *ngIf="hero">

  <h2>{{ hero.name | uppercase }} Details</h2>
  <div><span>id: </span>{{hero.id}}</div>
  <div>
    <label>name:
      <input [(ngModel)]="hero.name" placeholder="name"/>
    </label>
  </div>

</div>

hero property を Input デコレータとして追加する

HeroDetailComponent のテンプレートは Hero という型のプロパティをバインドしています。 HeroDetailComponentHero というシンボルをインポートします。

import { Hero } from '../hero';

次に、今まで詳細部分のテンプレートの実装を行なっていた「 heroes.component.html 」の詳細表示を、 HeroDetailComponent が実行されるように変更します。

<app-hero-detail [hero]="selectedHero"></app-hero-detail>

hero-detail.component.ts@angular/core のインポート文の所に Input を追加します。

import { Component, OnInit, Input } from '@angular/core';

最後に @Input() デコレータとして hero プロパティを hero-detail.component.ts に追加します。

export class HeroDetailComponent implements OnInit {
  @Input() hero: Hero;

  constructor() { }

  ngOnInit() {
  }

}

HeroDetailComponent を表示する

今のままではまだ詳細部分の表示はできないので、 HeroDetailComponent が実行されるように、 HeroesComponent 周りを修正していきます。

HeroesComponent の修正

heroes.component.htmlを修正します。

<app-hero-detail [hero]="selectedHero"></app-hero-detail>

このように修正することで、 HeroDetail をバインドするようになります。

heroes.component.html は最終的にこのようになります。

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

<app-hero-detail [hero]="selectedHero"></app-hero-detail>

前回からの変更点

前回の1つのコンポーネントによる実装から2つのコンポーネントにしたことによる変更点は下記の通りです。

  1. HeroesComponent の影響範囲を小さくして、簡略化を行なった。
  2. HeroesComponent を編集しなくても HeroDetailComponent を使って詳細部分のカスタマイズができるようになった。
  3. 詳細部分を意識することなく、一覧のカスタマイズができるようになった。
  4. 機能を分割したことで詳細部分を再利用することができるようになった。

機能分割を行うことでそれぞれの機能が分離されるため、コード変更時の影響範囲を軽減させながら、機能拡張性を高めることができました!

ソースコードについて

今までのソースコードは Github にあげてますので、詳細を確認したい方はこちらからソースコードを見てもらえればと思います。

最後に

今回のチュートリアルでコンポーネントの分割方法を理解することができました。コンポーネントを分割することで、作業分担も簡単になったり、コンポーネントの再利用性を高めることができるようになると思います。

また、コードのスパゲッティ化も防ぐこともできると思います。

ただ、あまりコンポーネントを分割しすぎても、管理やバインディングが煩雑になるので、どのサイズでコンポーネントを切り分けるかはプロジェクトの規模などに応じて決めていく必要があると思います。

コメントする

メールアドレスが公開されることはありません。 が付いている欄は必須項目です