前回の続き
今回は、大きくなってしまったAppComponentをサブコンポーネントに分けて、コンポーネントの役割をきちんと分ける。
サブコンポーネントを定義
まずは、AppComponentのサブコンポーネントとなるHeroDetailComponent
を./src/app/hero-detail.component.ts
を作成し、定義する。
import { Component } from '@angular/core';
@Component({
selector: 'hero-detail',
})
export class HeroDetailComponent {
}
ここで、いくつかポイントがある。
- コンポーネントを定義するためには、1行目のようにComponentシンボルをimportする
-
~Component
となるようにクラス名をつける - @ComponentのselectorはHTML上でのコンポーネントのタグ名になる
- コンポーネントクラスは常にexportする
サブコンポーネントにテンプレートを用意
サブコンポーネントがビューに表示するテンプレートを用意する。
AppComponentから以下と同じ箇所をカットし、hero-detail.component.tsに移動する。
@Component({
selector: 'hero-detail',
template: `
<div *ngIf="hero">
<h2>{{selectedHero.name}} details!</h2>
<div><label>id: </label>{{selectedHero.id}}</div>
<div>
<label>name: </label>
<input [(ngModel)]="selectedHero.name" placeholder="name">
</div>
</div>
`
})
このとき、*ngIf
部分をselectedHero
からhero
に変更する。
そうする理由は、サブコンポーネントでは、HeroDetailComponentクラスにhero
を定義し、こちらにバインドさせるから。
ということで、HeroDetailComponentクラスにhero
を定義する。
export class HeroDetailComponent {
hero: Hero;
}
Heroクラスを切り出す。
hero-detail.component.tsでもHeroクラスを参照することになったので、Heroクラスがapp.component.tsに定義されたままだと不都合。
Heroクラスを./src/app/hero.tsというファイルを作成し、こちらに移動させる。
export class Hero {
constructor(
public id: number,
public name: string,
) { }
}
クラスを切り出したので、app.component.tsとhero-detail.component.tsでHeroクラスをimportする。
import { Hero } from './hero';
子コンポーネントに値を渡す
app.component.tsからhero-detail.component.tsに値を渡す。
AppComponentのselectedHeroをHeroDetailComponentのhero
に受け渡す。
まずは、hero-detail.component.tsに@angular/coreに定義されているInput
をimportする。
Inputをimportしたことで、@Inportデコレータが使えるようになる。
import { Component, Input } from '@angular/core';
HeroDetailComponentのheroは外部から渡される変数なので、@Input
デコレータをつける。
@Input() hero: Hero;
AppModuleにHeroDetailComponentを宣言する
すべてのコンポーネントは、NgModuleに宣言されるべき。
ということで、app.module.ts
を開き、HeroDetailComponentをimportする。
import { HeroDetailComponent } from './hero-detail.component';
加えて、modulesの中のdeclarations
にも追加する。
declarations: [
AppComponent,
HeroDetailComponent
],
declarations配列は、モジュールに属するコンポーネントやパイプ(こいつは一体??)やディレクティブを含める。
他のコンポーネントがモジュールを参照できるようになる前に、コンポーネントはmoduleに宣言されるべき。
hero-detailセレクタを呼び出す
HeroDetailComponentをAppModuleに宣言したことで、app.component.tsでも使用できるようになった。
なので、templateでhero-detailセレクタを使用する。
<hero-detail [hero]="selectedHero"></hero-detail>
hero変数を[]
で囲み、=の右辺に渡したい値を記述することで、HeroDetailComponentのheroに値を渡すことができる。
終わりに
動作は前回と同じだが、サブコンポーネントとクラスに切り出したことでだいぶAppComponentがすっきりした。
まだまだリファクタリングの余地があるということで、次回でもリファクタリングを行うらしい。