サイトトップ

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

HTML5テクニカルノート

Angular 4入門 06: Routerを使う


Angular 4入門 05: リスト表示のコンポーネントを分ける」(以下「Angular 4入門 05」)の作例(コード001)では、コンポーネントのモジュールからリストのコンポーネントを分けました。さらに、Routerでページに加えるコンポーネントを切り替えましょう。Routerは、ページの表示やURLのパスを変えるナビゲーションの仕組みです。

01 Routerを加える

メインのコンポーネント(app.component)は、子コンポーネントの表示をナビゲートして切り替えることが役割になりました。そのためには、Routerを加えて設定しなければなりません。ナビゲーションには、ブラウザのアドレスバーに示すURLも含みます。まず、HTMLドキュメント(index.html)に加えなければならないのは、base要素href属性の定めです。すでに「Angular 4入門 01」コード001で、つぎのように書き加えておきました。

index.html

<head>
	<base href="/">

</head>

アプリケーションのモジュール(app.module)には、RouterModuleクラスimportします。すると、NgModule()デコレータ関数に渡す引数のオブジェクトのimportsプロパティに、RouterModule.forRoot()メソッドでつぎのようにURLのパス(pathプロパティ)と表示するコンポーネント(componentブロパティ)が定められます。画面を遷移したとき、ブラウザのアドレスバーにはこのパスが加わり、コンポーネントが表示されるのです。

app.module.ts


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

@NgModule({
	imports: [

		FormsModule,
		RouterModule.forRoot([
			{
				path: 'heroines',
				component: HeroinesComponent
			}
		])
	],

})
export class AppModule {}

つぎに、上記で定めたパスにいつ切り替え、コンポーネントをどこに表示するかです。メインのコンポーネント(app.component)のコードは、つぎのように書き替えます。<a>要素のリンクで切り替えるため、RouterLinkディレクティブにパスを与えます。そして、RouterOutletディレクティブを加えれば、リンクしたパスのコンポーネントがそこに差し込まれます(図001)。書き替えたふたつのモジュールは、以下のコード001にまとめました。

app.component.ts


@Component({

	template: `
		<h1>{{title}}</h1>
		<a routerLink="/heroines">ヒロインたち</a>
		<router-outlet></router-outlet>
	`
		/* <my-heroines></my-heroines>
	` */

})
export class AppComponent {

}

図001■リンクをクリックすると下にリストが表れる

図001

コード001■アプリケーションとメインのコンポーネント

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';
@NgModule({
	imports: [
		BrowserModule,
		FormsModule,
		RouterModule.forRoot([
			{
				path: 'heroines',
				component: HeroinesComponent
			}
		])
	],
	declarations: [
		AppComponent,
		HeroineDetailComponent,
		HeroinesComponent
	],
	providers: [HeroineService],
	bootstrap: [AppComponent]
})
export class AppModule {}

app.component.ts

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

02 ダッシュボードのコンポーネントを加える

初めにデフォルトとして、項目リストより先にダッシュボードを表示することにします。そのコンポーネント(dashboard.component)をつぎのように定めましょう。テンプレートはとりあえず「ダッシュボード」というテキストを示すだけです。

dashboard.component.ts

import {Component} from '@angular/core';
@Component({
	selector: 'my-dashboard',
	template: '<h3>ダッシュボード</h3>'
})
export class DashboardComponent {}

アプリケーションのモジュール(app.module)に、つぎのようにデコレータ関数(NgModule())の引数でコンポーネント(DashboardComponent)を加えます。RouterModule.forRoot()メソッドには、パス(dashboard)を定めたほか、指定がない('')ときのデフォルト転送先(redirectTo)としました(「Redirecting routes」参照)。そして、declarationsの配列に納めています。

app.module.ts


import {DashboardComponent} from './dashboard.component';

@NgModule({
	imports: [

		RouterModule.forRoot([
			{
				path: '',
				redirectTo: '/dashboard',
				pathMatch: 'full'
			},
			{
				path: 'dashboard',
				component: DashboardComponent
			},

		])
	],
	declarations: [
		AppComponent,
		DashboardComponent,

	],

})
export class AppModule {}

メインのコンポーネントには、つぎのように<a>要素でダッシュボードへのリンクを加え、ふたつ合わせて<nav>要素に含めます。パス(dashboard)はrouterLinkディレクティブで与えます。これで、初めにダッシュボードが表示されるようになりました(図002)。

app.component.ts


@Component({

	template: `

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

	`

})
export class AppComponent {

}

図002■初めにダッシュボードが表示される

図002

03 ダッシュボードに上位のリストを示す

ダッシュボードには、リストの上位4項目を掲げましょう。コンポーネントのクラス(DashboardComponent)に以下のようにOnInitクラスを実装し、コンストラクタでサービス(HeroineService)のインスタンスをプロパティ(heroineService)に与えます(OnInitクラスについては「Angular 4入門 04」02「コンポーネントのモジュールを書き替える」参照)。そして、ngOnInit()メソッドが呼び出されたとき、プロパティ(heroines)のリスト項目からArray.slice()メソッドで取り出した上位4つのエレメントを配列でプロパティ(heroines)に定めました。テンプレートは外部ファイル(dashboard.component.html)とし、デコレータ関数(Component())にパスをプロパティtemplateUrlで定めました。パスはコンポーネントからの相対パスで、必ず'./'で始めてください(「Angular 4でmoduleIdは要らなくなる」参照)。

dashboard.component.ts

// import {Component} from '@angular/core';
import {Component, OnInit} from '@angular/core';
import {Heroine} from './heroine';
import {HeroineService} from './heroine.service';
@Component({
	selector: 'my-dashboard',
	// template: '<h3>ダッシュボード</h3>'
	templateUrl: './dashboard.component.html'
})
// export class DashboardComponent {}
export class DashboardComponent implements OnInit {
	heroines: Heroine[] = [];
	constructor(private heroineService: HeroineService) {}
	ngOnInit(): void {
		this.heroineService.getHeroines()
		.then((heroines: Heroine[]) => this.heroines = heroines.slice(0, 4));
	}
}

ひとつ補っておきたいのは、サービス(HeroineService)のメソッドの呼び出しについてです。サービスは親のアプリケーションのモジュール(app.module)でデコレータ関数(NgModule())の引数オブジェクトにprovidersとして配列エレメントに加えてありました(「Angular 4入門 05」02「アプリケーションのモジュールにリスト表示のコンポーネントを組み込む」)。そうすることで、子のコンポーネントがサービスの同じインスタンスを使えるのです。

app.module.ts

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

	providers: [HeroineService],

})
export class AppModule {}

テンプレートはつぎのようにngForディレクティブで、プロパティ(heroines)の配列から取り出した項目を順に要素に加えています(図003)。ダッシュボードを加えるために書き替えた3つのモジュールは、以下のコード002にまとめたとおりです。併せて、Plunkerに作例のコードを掲げます。

dashboard.component.html

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

図003■ダッシュボードに示された上位のリスト

図003

コード002■ダッシュボードを加えるために書き替えた3つのモジュール

dashboard.component.ts

import {Component, OnInit} from '@angular/core';
import {Heroine} from './heroine';
import {HeroineService} from './heroine.service';
@Component({
	selector: 'my-dashboard',
	templateUrl: './dashboard.component.html'
})
export class DashboardComponent implements OnInit {
	heroines: Heroine[] = [];
	constructor(private heroineService: HeroineService) {}
	ngOnInit(): void {
		this.heroineService.getHeroines()
		.then((heroines: Heroine[]) => this.heroines = heroines.slice(0, 4));
	}
}

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
			}
		])
	],
	declarations: [
		AppComponent,
		DashboardComponent,
		HeroineDetailComponent,
		HeroinesComponent
	],
	providers: [HeroineService],
	bootstrap: [AppComponent]
})
export class AppModule {}

app.component.ts

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


作成者: 野中文雄
更新日: 2017年6月18日 03「ダッシュボードに上位のリストを示す」に、サービスのメソッド呼び出しについて補足。
更新日: 2017年6月13日 03「ダッシュボードに上位のリストを示す」に、相対パスの書き方についての注意と参考記事へのリンクを追加。
作成日: 2017年6月8日


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