サイトトップ

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

HTML5テクニカルノート

Angular 4入門 07: Routerで画面を遷移させる


Angular 4入門 06: Routerを使う」(以下「Angular 4入門 06」)の作例(コード002)は、Routerでページに加えるコンポーネントを切り替えました。今回は遷移する画面を、ダッシュボードとリスト表示および詳細情報の3つに整理します。さらに、テンプレートやスタイルは外部ファイルに分けましょう。手数は少し多いので、先にでき上がりを確かめたい方は「Angular 4 Example - Tour of Heroines: Part 7」をご覧ください。

Angular Version 5については「Angular 5入門 07: ルーティングで個別情報を示す」をお読みください。

01 詳細情報のコンポーネントからテンプレートを外部ファイルに分ける

まず、詳細情報のコンポーネント(heroine-detail.component)のテンプレートを、外部ファイル(heroine-detail.component.html)に分けましょう。つぎのように、デコレータ関数(Component())に渡すオブジェクトに、templateUrlプロパティを定めます(「Angular 4入門 06」03「ダッシュボードに上位のリストを示す」参照)。もちろん、アプリケーションの動きは、そのまま変わりません。

heroine-detail.component.ts

@Component({

	/* template: `
		<div *ngIf="heroine">
			<h2>{{heroine.name}}の情報</h2>
			<div><label>番号: </label>{{heroine.id}}</div>
			<div>
				<label>名前: </label>
				<input [(ngModel)]="heroine.name" placeholder="名前">
			</div>
		</div>
	` */
	templateUrl: './heroine-detail.component.html'
})
export class HeroineDetailComponent {

}

heroine-detail.component.html

<div *ngIf="heroine">
	<h2>{{heroine.name}}の情報</h2>
	<div><label>番号: </label>{{heroine.id}}</div>
	<div>
		<label>名前: </label>
		<input [(ngModel)]="heroine.name" placeholder="名前">
	</div>
</div>

02 詳細情報からボタンでダッシュボードに戻る

詳細情報のテンプレート(heroine-detail.component.html)には、つぎのように前の画面に戻る<button>要素を加えます。clickイベントで呼び出すメソッド(goBack())は、この後コンポーネント(heroine-detail.component)に定めます。

heroine-detail.component.html

<div *ngIf="heroine">

	<div>

	</div>
	<button (click)="goBack()">戻る</button>
</div>

詳細情報のコンポーネント(heroine-detail.component)には、つぎのように@angularのモジュールの3つのクラス(ActivatedRouteParamsおよびLocation)、そしてサービスのクラス(HeroineService)をimportします。すると、コンストラクタには3つのクラスのインスタンスが渡されますので、それらをprivateのプロパティ(heroineServiceとrouteおよびlocation)に納めておきます。新たに加えたメソッド(goBack())は、Location.back()メソッドでブラウザの履歴にしたがってURLを戻ります(図001)。

heroine-detail.component.ts

import {ActivatedRoute, Params} from '@angular/router';
import {Location} from '@angular/common';

export class HeroineDetailComponent {

	constructor(
		private route: ActivatedRoute,
		private location: Location
	) {}
	goBack(): void {
		this.location.back();
	}
}

図001■詳細情報のボタンをクリックするとダッシュボードに戻る

図001

03 ダッシュボードから詳細情報のURLに移る

ダッシュボードのコンポーネント(dashboard.component)で上位リストをリンクにして、クリックしたらID番号も示された詳細情報の画面のURLに移るようにしてみます。テンプレート(dashboard.component.html)は、つぎのように項目を<a>要素に書き替えます。リンクを動的に決めるときは、routerLinkディレクティブを角かっこ[]の中に書き、値となるパスの情報は配列で加えます。そして、アプリケーションのモジュール(app.module)ではクラスのデコレータ関数(NgModule())のimportsプロパティで、RouterModule.forRoot()メソッドの引数配列に渡す要素として、パス(path)とコンポーネント(component)のプロパティが備わったオブジェクトを新たに加えれば、クリックした項目の詳細情報にURLが移ります。ただし、選択した項目のデータはコンポーネントに送られませんので、情報が何も示されません(図002)。

dashboard.component.html

<h3>トップヒロイン</h3>
<div class="grid grid-pad">
	<!--<div *ngFor="let heroine of heroines" class="col-1-4">-->
	<a *ngFor="let heroine of heroines" [routerLink]="['/detail', heroine.id]" class="col-1-4">

	<!--</div>-->
	</a>
</div>

app.module.ts

@NgModule({
	imports: [

		RouterModule.forRoot([
			{

			},
			{
				path: 'detail/:id',
				component: HeroineDetailComponent
			}
		])
	],

})
export class AppModule {}

図002■ダッシュボードの上位リストをクリックすると詳細情報のURLに移る

04 ダッシュボードで選択した項目のデータを詳細情報のコンポーネントに示す

詳細情報のURLには、id番号が添えてありました。この値は、あとに述べるやり方で調べられます。また、サービス(heroine.service)のモジュールからは、idの含まれたすべての項目のリストが得られました。すると、idを頼りにして項目の情報が取り出せるということです。そのメソッド(getHeroine())も、つぎのようにサービスに加えましょう。引数の値(id)から、Array.find()メソッドで当てはまる項目のオブジェクトを探して返します。

heroine.service.ts

export class HeroineService {
	getHeroines(): Promise<Heroine[]> {

	}
	getHeroine(id: number): Promise<Heroine> {
		return this.getHeroines()
		.then((heroines: Heroine[]) => heroines.find((heroine: Heroine) => heroine.id === id));
	}
}

詳細情報のコンポーネント(heroine-detail.component)には、コンストラクタでサービス(HeroineService)とActivatedRouteオブジェクトをprivateのプロパティ(heroineServiceおよびroute)に定めてありました。さらに、RxJSのswitchMapオペレータとAngular 2のクラスOnInitを、つぎのようにimportします。ngOnInit()メソッドは、ActivatedRoute.paramsプロパティからswitchMapオペレータで関数を呼び出します(「Angular 2 Router v3.0.0-alpha.3を触ってみた」の「パラメータの受け取り」参照)。さらに、関数は引数(params)のオブジェクトからidプロパティ値が得られますますので、サービスのメソッド(getHeroine())に渡して対応する項目のオブジェクトを受け取るという流れです(引数に+演算子を加えたのは数値に変換するためです)。オブジェクトが得られたら、subscribeオペレータでプロパティに定めます(「これだけ知ってれば大丈夫(かもしれない)RxJS5の厳選オペレータ」参照)。

heroine-detail.component.ts

import 'rxjs/add/operator/switchMap';
// import {Component, Input} from '@angular/core';
import {Component, Input, OnInit} from '@angular/core';
import {ActivatedRoute, Params} from '@angular/router';

import {HeroineService} from './heroine.service';
// export class HeroineDetailComponent {
export class HeroineDetailComponent implements OnInit {

	constructor(
		private heroineService: HeroineService,
		private route: ActivatedRoute,

	) {}
	ngOnInit(): void {
		this.route.params
		.switchMap((params: Params) => this.heroineService.getHeroine(+params['id']))
		.subscribe((heroine: Heroine) => this.heroine = heroine);
	}

}

これで詳細情報のコンポーネントに、パスのidと一致する項目、つまりダッシュボードで選択された項目のデータが示されます(図003)。ダッシュボードから詳細情報の画面に移すために、書き改めたモジュールとテンプレートは以下のコード001にまとめました。また、ここまでの確認用として「Angular 4 Example - Tour of Heroines: Part 7-1」を掲げます。

図003■ダッシュボードのでクリックした項目のデータが詳細情報に示される

図003

コード001■ダッシュボードから詳細情報の画面に移すために書き改めたモジュールとテンプレート

heroine.service.ts

import {Injectable} from '@angular/core';
import {Heroine} from './heroine';
import {HEROINES} from './mock-heroines';
@Injectable()
export class HeroineService {
	getHeroines(): Promise<Heroine[]> {
		return Promise.resolve(HEROINES);
	}
	getHeroine(id: number): Promise<Heroine> {
		return this.getHeroines()
		.then((heroines: Heroine[]) => heroines.find((heroine: Heroine) => heroine.id === id));
	}
}

heroine-detail.component.ts

import 'rxjs/add/operator/switchMap';
import {Component, Input, OnInit} from '@angular/core';
import {ActivatedRoute, Params} from '@angular/router';
import {Location} from '@angular/common';
import {Heroine} from './heroine';
import {HeroineService} from './heroine.service';
@Component({
	selector: 'heroine-detail',
	templateUrl: './heroine-detail.component.html'
})
export class HeroineDetailComponent implements OnInit {
	@Input()
	heroine: Heroine;
	constructor(
		private heroineService: HeroineService,
		private route: ActivatedRoute,
		private location: Location
	) {}
	ngOnInit(): void {
		this.route.params
		.switchMap((params: Params) => this.heroineService.getHeroine(+params['id']))
		.subscribe((heroine: Heroine) => this.heroine = heroine);
	}
	goBack(): void {
		this.location.back();
	}
}

app.module.ts

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

heroine-detail.component.html

<div *ngIf="heroine">
	<h2>{{heroine.name}}の情報</h2>
	<div><label>番号: </label>{{heroine.id}}</div>
	<div>
		<label>名前: </label>
		<input [(ngModel)]="heroine.name" placeholder="名前">
	</div>
	<button (click)="goBack()">戻る</button>
</div>

dashboard.component.html

<h3>トップヒロイン</h3>
<div class="grid grid-pad">
	<a *ngFor="let heroine of heroines" [routerLink]="['/detail', heroine.id]" class="col-1-4">
		<div class="module heroine">
			<h4>{{heroine.name}}</h4>
		</div>
	</a>
</div>

05 テンプレートとスタイルを外部ファイルに分ける

項目リストのコンポーネント(heroines.component.ts)は、テンプレートとスタイルを別ファイルに分けましょう。前述のとおりテンプレートのHTMLファイル(heroines.component.html)は、デコレータ関数(Component())に渡すオブジェクトのtemplateUrlプロパティに定めます。スタイルのCSSファイル(heroines.component.css)のパスは、つぎのようにstyleUrlsプロパティに配列エレメントとして加えます。

heroines.component.ts

@Component({
	selector: 'my-heroines',
	/* template: `

		`, */
	templateUrl: './heroines.component.html',
	/* styles: [`

	`] */
	styleUrls: ['./heroines.component.css']
})
export class HeroinesComponent implements OnInit {

}

heroines.component.html

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

heroines.component.css

.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: .8em;
	border-radius: 4px 0 0 4px;
}

06 Routerのモジュールを分ける

アプリケーションのモジュール(app.module)から、Routerの仕事も分けることにします。Routerのモジュール(app-routing.module)には、アプリケーションのコードをコピーしてつぎのように書き替えます。パスとコンポーネントの配列は、わかりやすいように予め定数(routes)に納めました。RouterModuleクラスは、デコレータ関数(NgModule())に渡すオブジェクトのexportsプロパティに、配列エレメントとして与えます。こうすることで、このモジュールをデコレータ関数のimportsに加えたモジュールのコンポーネントから、RouterLinkRouterOutletといったRouterのディレクティブが使えるようになるのです。

app.module.ts→app-routing.module.ts

import {NgModule} from '@angular/core';
// import {BrowserModule} from '@angular/platform-browser';
// import {FormsModule} from '@angular/forms';
// import {RouterModule} from '@angular/router';
import {RouterModule, Routes} from '@angular/router';
// import {AppComponent} from './app.component';
import {HeroineDetailComponent} from './heroine-detail.component';
import {HeroinesComponent} from './heroines.component';
// import {HeroineService} from './heroine.service';
import {DashboardComponent} from './dashboard.component';
const routes: Routes = [
	{
		path: '',
		redirectTo: '/dashboard',
		pathMatch: 'full'
	},
	{
		path: 'dashboard',
		component: DashboardComponent
	},
	{
		path: 'heroines',
		component: HeroinesComponent
	},
	{
		path: 'detail/:id',
		component: HeroineDetailComponent
	}
];
@NgModule({
	imports: [
		/* BrowserModule,
		FormsModule,
		RouterModule.forRoot([

		]) */
		RouterModule.forRoot(routes)
	],
	/* declarations: [
		AppComponent,
		DashboardComponent,
		HeroineDetailComponent,
		HeroinesComponent
	],
	providers: [HeroineService],
	bootstrap: [AppComponent] */
	exports: [RouterModule]
})
// export class AppModule {}
export class AppRoutingModule {}

アプリケーション(app.module)は、つぎのようにRouterのコードを除く替わりに、Routerモジュールのクラス(AppRoutingModule)を読み込み、デコレータ関数(NgModule())のimportsに加えます。ここまで書き替えたリスト表示(heroines.component)とRouterおよびアプリケーションのモジュールは、以下のコード002にまとめました。リスト表示のコンポーネントから外部ファイルに分けたテンプレート(heroines.component.html)とスタイル(heroines.component.css)は前掲のとおりですので省きます。ここまでのコードは「Angular 4 Example - Tour of Heroines: Part 7-2」に掲げましたので、それぞれのファイルの中身はこちらでお確かめください。

app.module.ts

// import {RouterModule} from '@angular/router';

import {AppRoutingModule} from './app-routing.module';
@NgModule({
	imports: [

		/* RouterModule.forRoot([

		]) */
		AppRoutingModule
	],

})
export class AppModule {}

コード002■書き替えたリスト表示とRouterおよびアプリケーションのモジュール

heroines.component.ts

import {Component, OnInit} from '@angular/core';
import {Heroine} from './heroine';
import {HeroineService} from './heroine.service';
@Component({
	selector: 'my-heroines',
	templateUrl: './heroines.component.html',
	styleUrls: ['./heroines.component.css']
})
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-routing.module.ts

import {NgModule} from '@angular/core';
import {RouterModule, Routes} from '@angular/router';
import {HeroineDetailComponent} from './heroine-detail.component';
import {HeroinesComponent} from './heroines.component';
import {DashboardComponent} from './dashboard.component';
const routes: Routes = [
    {
        path: '',
        redirectTo: '/dashboard',
        pathMatch: 'full'
    },
    {
        path: 'dashboard',
        component: DashboardComponent
    },
    {
        path: 'heroines',
        component: HeroinesComponent
    },
    {
        path: 'detail/:id',
        component: HeroineDetailComponent
    }
];
@NgModule({
    imports: [RouterModule.forRoot(routes)],
    exports: [RouterModule]
})
export class AppRoutingModule {}

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';
import {DashboardComponent} from './dashboard.component';
import {AppRoutingModule} from './app-routing.module';
@NgModule({
    imports: [
        BrowserModule,
        FormsModule,
        AppRoutingModule
    ],
    declarations: [
        AppComponent,
        DashboardComponent,
        HeroineDetailComponent,
        HeroinesComponent
    ],
    providers: [HeroineService],
    bootstrap: [AppComponent]
})
export class AppModule {}

07 詳細情報のナビゲーションを整理する

リスト表示のコンポーネント(heroines.component)で項目をクリックすると、詳細情報はリストの下に示されました(前掲図001参照)。これを、ダッシュボードと同じように、別画面で表示するようにしましょう。そのため、テンプレート(heroines.component.html)はつぎのように書き替えて、ボタンで詳細情報のURLに移るようにします。ボタンクリックで呼び出すメソッド(gotoDetail())は、このあとコンポーネントに加えます。

heroines.component.html

<ul class="heroines">

</ul>
<div *ngIf="selectedHeroine">
	<h2>
		ヒロイン「{{selectedHeroine.name}}」
	</h2>
	<button (click)="gotoDetail()">詳細を見る</button>
</div>
<!-- <heroine-detail [heroine]="selectedHeroine"></heroine-detail> -->

リスト表示のコンポーネント(heroines.component)は、つぎのようにRouterクラスをimportし、コンストラクタで引数として受け取ったインスタンスをprivateのプロパティ(router)に与えます。すると、Router.navigate()メソッドで、引数に渡した配列の定めるパスに移れるのです(「Angular 2 Router v3.0.0-alpha.3を触ってみた」の「ナビゲーション」参照)。ボタンクリックで呼び出されるメソッド(gotoDetail())に、この処理を加えました。これで、リストの項目を選ぶと「詳細を見る」ボタンが表れ(図004)、クリックすればダッシュボードの場合と同じ詳細情報の画面が示されます(前掲図003)。

heroines.component.ts

import {Router} from '@angular/router';

export class HeroinesComponent implements OnInit {

	constructor(
		private router: Router,
		private heroineService: HeroineService
	) {}

	gotoDetail(): void {
		this.router.navigate(['/detail', this.selectedHeroine.id]);
	}
}

図004■リストの項目を選ぶと「詳細を見る」ボタンが表れる

図004

08 メインのコンポーネントにスタイルを定める

メインのコンポーネントにもスタイルを定めましょう。CSSファイルは「Angular Example - Tour of Heroes: Part 5」のapp.component.cssを使わせてもらいます。ファイルまたはつぎのコードをそのままコピーしてしまって構いません。

app.component.css

h1 {
	font-size: 1.2em;
	color: #999;
	margin-bottom: 0;
}
h2 {
	font-size: 2em;
	margin-top: 0;
	padding-top: 0;
}
nav a {
	padding: 5px 10px;
	text-decoration: none;
	margin-top: 10px;
	display: inline-block;
	background-color: #eee;
	border-radius: 4px;
}
nav a:visited, a:link {
	color: #607D8B;
}
nav a:hover {
	color: #039be5;
	background-color: #CFD8DC;
}
nav a.active {
	color: #039be5;
}

そのうえで、メインのコンポーネント(app.component)のデコレータ関数(Component())には、引数のオブジェクトにstyleUrlsプロパティをつぎのように与えます。もうひとつ、リンクの<a>要素には、routerLinkActiveディレクティブにCSSのクラス(active)を定めました。リンクがアクティブになると、このクラスは動的に加えられます。ダッシュボードとリスト表示のどちらが選ばれているかで、要素のスタイルが変わるということです(図005)。書き改めたリスト表示のコンポーネント(app.component.ts)のテンプレートとコード、およびメインのコンポーネント(app.component)は、以下のコード003にまとめました。併せて「Angular 4 Example - Tour of Heroines: Part 7-3」を掲げますので、他のファイルのコードについてはこちらをお確かめください。

app.component.ts

@Component({

	template: `


		<nav>
			<a routerLink="/dashboard" routerLinkActive="active">ダッシュボード</a>
			<a routerLink="/heroines" routerLinkActive="active">ヒロインたち</a>
		</nav>

		`,
	styleUrls: ['./app.component.css']
})
export class AppComponent {

}

図005■アクティブなリンクのスタイルが変わる

図005

コード003■リスト表示のコンポーネントのテンプレートとコードおよびメインのコンポーネント

heroines.component.html

<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>
<div *ngIf="selectedHeroine">
	<h2>
		ヒロイン「{{selectedHeroine.name}}」
	</h2>
	<button (click)="gotoDetail()">詳細を見る</button>
</div>

heroines.component.ts

import {Component, OnInit} from '@angular/core';
import {Router} from '@angular/router';
import {Heroine} from './heroine';
import {HeroineService} from './heroine.service';
@Component({
	selector: 'my-heroines',
	templateUrl: './heroines.component.html',
	styleUrls: ['./heroines.component.css']
})
export class HeroinesComponent implements OnInit {
	heroines: Heroine[];
	selectedHeroine: Heroine;
	constructor(
		private router: Router,
		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();
	}
	gotoDetail(): void {
		this.router.navigate(['/detail', this.selectedHeroine.id]);
	}
}

app.component.ts

import {Component} from '@angular/core';
@Component({
	selector: 'my-app',
	template: `
		<h1>{{title}}</h1>
		<nav>
			<a routerLink="/dashboard" routerLinkActive="active">ダッシュボード</a>
			<a routerLink="/heroines" routerLinkActive="active">ヒロインたち</a>
		</nav>
		<router-outlet></router-outlet>
	`,
	styleUrls: ['./app.component.css']
})
export class AppComponent {
	title = 'ヒロイン一覧';
}

09 スタイルを仕上げる

Routerを使ったアプリケーションの動きそのものはこれででき上がりといえます。後は、スタイルを整えましょう。使うのは、やはり前掲「Angular Example - Tour of Heroes: Part 5」のCSSファイルです。詳細情報のコンポーネント(heroine-detail.component)には、同じ名前のつぎのCSSファイル(heroine-detail.component.css)を定め、コードをコピーします。そして、デコレータ関数(Component())に渡すオブジェクトのstyleUrlsに配列エレメントとして加えてください。

heroine-detail.component.css

label {
	display: inline-block;
	width: 3em;
	margin: .5em 0;
	color: #607D8B;
	font-weight: bold;
}
input {
	height: 2em;
	font-size: 1em;
	padding-left: .4em;
}
button {
	margin-top: 20px;
	font-family: Arial;
	background-color: #eee;
	border: none;
	padding: 5px 10px;
	border-radius: 4px;
	cursor: pointer; cursor: hand;
}
button:hover {
	background-color: #cfd8dc;
}
button:disabled {
	background-color: #eee;
	color: #ccc; 
	cursor: auto;
}

heroine-detail.component.ts

@Component({

	templateUrl: './heroine-detail.component.html',
	styleUrls: ['./heroine-detail.component.css']
})
export class HeroineDetailComponent implements OnInit {

}

ダッシュボードのコンポーネント(dashboard.component)にも、「Angular Example - Tour of Heroes: Part 5」から同じ名前のCSSファイルを定めます。つぎのコードをそのままコピーしてしまって構いません。こちらも、デコレータ関数(Component())のstyleUrlsに配列エレメントとして加えます。これで、見栄えはずっとよくなるでしょう(図006)。

dashboard.component.css

[class*='col-'] {
	float: left;
	padding-right: 20px;
	padding-bottom: 20px;
}
[class*='col-']:last-of-type {
	padding-right: 0;
}
a {
	text-decoration: none;
}
*, *:after, *:before {
	-webkit-box-sizing: border-box;
	-moz-box-sizing: border-box;
	box-sizing: border-box;
}
h3 {
	text-align: center; margin-bottom: 0;
}
h4 {
	position: relative;
}
.grid {
	margin: 0;
}
.col-1-4 {
	width: 25%;
}
.module {
	padding: 20px;
	text-align: center;
	color: #eee;
	max-height: 120px;
	min-width: 120px;
	background-color: #607D8B;
	border-radius: 2px;
}
.module:hover {
	background-color: #EEE;
	cursor: pointer;
	color: #607d8b;
}
.grid-pad {
	padding: 10px 0;
}
.grid-pad > [class*='col-']:last-of-type {
	padding-right: 20px;
}
@media (max-width: 600px) {
	.module {
		font-size: 10px;
		max-height: 75px;
	}
}
@media (max-width: 1024px) {
	.grid {
		margin: 0;
	}
	.module {
		min-width: 60px;
	}
}

dashboard.component.ts

@Component({

	templateUrl: './dashboard.component.html',
	styleUrls: ['./dashboard.component.css']
})
export class DashboardComponent implements OnInit {

}

図006■スタイルが与えられたダッシュボード

図006

10 要らなくなったコードを除く

スクリプトの仕上げとして、詳細情報のコンポーネント(heroine-detail.component)から要らなくなったコードを除きます。関数Input()でプロパティ(heroine)をデコレートしたのは、親コンポーネント(app.component)から値が受け取れるようにするためでした(「Angular 4入門 03」02「コンポーネントをふたつのモジュールに分ける」参照)。けれど、前述04「ダッシュボードで選択した項目のデータを詳細情報のコンポーネントに示す」で、コンポーネントはサービス(heroine.service)からプロパティ値を得るようになっています。したがって、デコレータ関数とそのimportはもはや要りません。でき上がりは、冒頭にも掲げた「Angular 4 Example - Tour of Heroines: Part 7」でお確かめください。

heroine-detail.component.ts

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

export class HeroineDetailComponent implements OnInit {
	// @Input()
	heroine: Heroine;

}


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


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