サイトトップ

Director Flash 書籍 業務内容 プロフィール

HTML5テクニカルノート

Angular 4入門 05: リスト表示のコンポーネントを分ける


Angular 4入門 04: サービスをつくる」(以下「Angular 4入門 04」)の作例(コード002)では、複数のコンポーネントに共通のデータが与えられるように、サービスという仕組みにモジュールを切り分けました。さらにコンポーネント分けを進めましょう。

Angular Version 5については「Angular 5入門 04: 詳細情報のコンポーネントを分ける」をお読みください。

01 コンポーネントのモジュールからリストのコンポーネントを分ける

前出「Angular 4入門 04」コード002では、コンポーネントのモジュール(app.component)が項目をリスト表示しました。このリスト表示の仕事は、別のモジュール(heroines.component)に分けます(「app」フォルダ内)。メインのコンポーネントとして、ナビゲーションに専念させるためです。リスト表示のコンポーネントは、つぎのように親コンポーネントのコードのコードのほとんどを受け継ぎます(略したコードは親コンポーネントのままです)。

app.component.ts→heroines.component.ts

import {Component, OnInit} from '@angular/core';
import {Heroine} from './heroine';
import {HeroineService} from './heroine.service';
@Component({
	selector: 'my-heroines',  // 'my-app',
		/* <h1>{{title}}</h1> */
	template: `
		<h2>ヒロインたち</h2>
		<ul class="heroines">
			/* [中略] */
		</ul>
		<heroine-detail [heroine]="selectedHeroine"></heroine-detail>
	`,
	styles: [`
		/* [中略] */
	`] /* ,
	providers: [HeroineService] */
})
// export class AppComponent {
export class HeroinesComponent implements OnInit {
	// title = 'ヒロイン一覧';
	heroines: Heroine[];
	selectedHeroine: Heroine;
	constructor(private heroineService: HeroineService) {}
	/* [中略] */
}

すると、親コンポーネント(app.component)は、一旦つぎのような質素なつくりになります。後のち子コンポーネントが増えたら、それらのナビゲーションを加えていくつもりです。

app.component.ts

import {Component /*, OnInit */} from '@angular/core';
// import {Heroine} from './heroine';
// import {HeroineService} from './heroine.service';
@Component({
	selector: 'my-app',
	template: `
		<h1>{{title}}</h1>
		<my-heroines></my-heroines>
	`
		/* <h2>ヒロインたち</h2>

	`,
	styles: [`

	`],
	providers: [HeroineService] */
})
export class AppComponent {
	title = 'ヒロイン一覧';
	/* heroines: Heroine[];
	selectedHeroine: Heroine;
	constructor(private heroineService: HeroineService) {}
	onSelect(heroine: Heroine): void {

	}
	getHeroines(): void {

	}
	ngOnInit(): void {

	} */
}

02 アプリケーションのモジュールにリスト表示のコンポーネントを組み込む

アプリケーションのモジュール(app.module)には、つぎのようにリスト表示の子コンポーネント(heroines.component)を加えなければなりません。併せて、サービスのモジュール(heroine.service)も組み込みます。そして、デコレータ関数(NgModule())に渡す引数のオブジェクトにprovidersとして定めました。モジュールの組み立てを変えただけですから、アプリケーションの動きは変わりません(図001)。ここまで書いたリスト表示(heroines.component)とメインのコンポーネント(app.component)およびアプリケーションのモジュール(app.module)を、以下のコード001にまとめました。併せて、Plunkerに作例のコードを掲げておきます。

app.module.ts


import {HeroinesComponent} from './heroines.component';
import {HeroineService} from './heroine.service';
@NgModule({

	declarations: [

		HeroineDetailComponent,
		HeroinesComponent
	],
	providers: [HeroineService],

})
export class AppModule {}

図001■リストの項目をクリックすると下にその情報が表れる

図001

コード001■リスト表示とメインのコンポーネントおよびアプリケーションのモジュール

heroines.component.ts

import {Component, OnInit} from '@angular/core';
import {Heroine} from './heroine';
import {HeroineService} from './heroine.service';
@Component({
	selector: 'my-heroines',
	template: `
		<h2>ヒロインたち</h2>
		<ul class="heroines">
			<li *ngFor="let heroine of heroines"
				[class.selected]="heroine === selectedHeroine"
				(click)="onSelect(heroine)">
				<span class="badge">{{heroine.id}}</span> {{heroine.name}}
			</li>
		</ul>
		<heroine-detail [heroine]="selectedHeroine"></heroine-detail>
	`,
	styles: [`
		.selected {
			background-color: #CFD8DC !important;
			color: white;
		}
		.heroines {
			margin: 0 0 2em 0;
			list-style-type: none;
			padding: 0;
			width: 15em;
		}
		.heroines li {
			cursor: pointer;
			position: relative;
			left: 0;
			background-color: #EEE;
			margin: 0.5em;
			padding: 0.3em 0;
			height: 1.6em;
			border-radius: 4px;
		}
		.heroines li.selected:hover {
			background-color: #BBD8DC !important;
			color: white;
		}
		.heroines li:hover {
			color: #607D8B;
			background-color: #DDD;
			left: 0.1em;
		}
		.heroines .text {
			position: relative;
			top: -3px;
		}
		.heroines .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: 0.8em;
			border-radius: 4px 0 0 4px;
		}
	`]
})
export class HeroinesComponent implements OnInit {
	heroines: Heroine[];
	selectedHeroine: Heroine;
	constructor(private heroineService: HeroineService) {}
	onSelect(heroine: Heroine): void {
		this.selectedHeroine = heroine;
	}
	getHeroines(): void {
		this.heroineService.getHeroines().then((heroines: Heroine[]) => this.heroines = heroines);
	}
	ngOnInit(): void {
		this.getHeroines();
	}
}

app.component.ts

import {Component} from '@angular/core';
@Component({
	selector: 'my-app',
	template: `
		<h1>{{title}}</h1>
		<my-heroines></my-heroines>
	`
})
export class AppComponent {
	title = 'ヒロイン一覧';
}

app.module.ts

import {NgModule} from '@angular/core';
import {BrowserModule} from '@angular/platform-browser';
import {FormsModule} from '@angular/forms';
import {AppComponent} from './app.component';
import {HeroineDetailComponent} from './heroine-detail.component';
import {HeroinesComponent} from './heroines.component';
import {HeroineService} from './heroine.service';
@NgModule({
	imports: [
		BrowserModule,
		FormsModule
	],
	declarations: [
		AppComponent,
		HeroineDetailComponent,
		HeroinesComponent
	],
	providers: [HeroineService],
	bootstrap: [AppComponent]
})
export class AppModule {}


作成者: 野中文雄
作成日: 2017年6月6日


Copyright © 2001-2017 Fumio Nonaka.  All rights reserved.