HTML5テクニカルノート
Angular 5入門 06: ルーティングで画面を切り替える
- ID: FN1801005
- Technique: HTML5 / JavaScript
- Package: Angular 5.2.1
「Angular 5入門 05: データをサービスにより提供する」は、データの取得や提供などの管理を、サービスのモジュールに分けました。本稿では、ルーティングの機能によって画面を切り替えます。ページのコンポーネントを差し替えるだけでなく、URLも改めることでページの遷移を示すのです。
Angular Version 6については「Angular 6入門 06: ルーティングで画面を切り替える」をお読みください
01 ルーティングのモジュールをつくる
ルーティングのモジュールをAngular CLIでつくります。コマンドラインツールでアプリケーションのディレクトリ(angular-tour-of-heroines)に移り、つぎのようにng generate module
コマンドを打ち込んでください。ルーティングのモジュール(app-routing.module)がつくられ、以下のようなひな形のクラス(AppRoutingModule)が定められます。
ngコマンドng generate module app-routing --flat --module=app
src/app/app-routing.module.tsimport {NgModule} from '@angular/core'; import {CommonModule} from '@angular/common'; @NgModule({ imports: [ CommonModule ], declarations: [] }) export class AppRoutingModule {}
ルーティングのモジュール(app-routing.module)のTypeScriptコードは、つぎのように書き替えましょう。ルーティングのライブラリ(app-routing.module)からRouterModule
クラスとRoutes
型(type alias)をimport
します。そのうえで、クラスはデコレータ関数NgModule()
の引数オブジェクトに、exports
プロパティの配列要素として加えてください。プロパティimports
とdeclarations
は除きます。
src/app/app-routing.module.tsimport {NgModule} from '@angular/core'; // import {CommonModule} from '@angular/common'; import {RouterModule, Routes} from '@angular/router'; @NgModule({ /* imports: [ CommonModule ], declarations: [] */ exports: [RouterModule] }) export class AppRoutingModule {}
Routes
型の定数(routes)に、以下のようにパス('heroines')とコンポーネント(HeroinesComponent)が定められたオブジェクトを配列要素として加えます。そのため、コンポーネントのクラス(HeroinesComponent)は、import
しておかなければなりません。Routes
オブジェクトのプロパティpath
はURLのパスに加える文字列で、component
はそのパスに遷移するときつくられるコンポーネントです。RouterModule.forRoot()
メソッドは、引数のRoutes
オブジェクトにもとづいてルーターを初期化します。そして、戻り値のモジュールを、デコレータ関数NgModule()
に渡すオブジェクトのimports
プロパティに配列要素として加えることで、ルーティングのためのサービスやディレクティブが使えるようになるのです(「URLとリンクでコンポーネント表示を切り替える「Angular 2」のルーター」参照)。
src/app/app-routing.module.tsimport {HeroinesComponent} from './heroines/heroines.component'; const routes: Routes = [ {path: 'heroines', component: HeroinesComponent} ]; @NgModule({ imports: [RouterModule.forRoot(routes)], }) export class AppRoutingModule {}
02 コンポーネントにルーティングの要素を加える
親コンポーネント(app.component)のテンプレートは、つぎのように要素を子コンポーネントの(app-heroines)からrouter-outlet
(RouterOutlet
)ディレクティブに差し替えます。router-outlet
はルーティングが遷移した表示に切り替えるディレクティブです。このディレクティブの要素には、はじめは何も表示されません(図001)。
src/app/app.component.html<h1>{{title}}</h1> <!--<app-heroines></app-heroines>--> <router-outlet></router-outlet> <app-messages></app-messages>
図001■router-outletの要素にははじめ何も表示されない
ここで、ブラウザのルートURLに、つぎのように前述path
プロパティに与えたパスを加えます。すると、ルーテイングによりrouter-outletディレクティブの要素には、コンポーネントが差し込まれます(図002)。
http://localhost:4200/heroines
図002■ページにコンポーネントが差し込まれて表示される
なお、router-outlet
は、RouterModule
クラスから提供されるディレクティブです。このクラスはルーテイングのモジュール(app-routing.module)がNgModule()
デコレータ関数に渡したオブジェクトのexports
プロパティに配列要素として加え、そのクラス(AppRoutingModule)をアプリケーションモジュール(app.module)のimports
プロパティが配列に納めました。こうして、アプリケーションのコンポーネントがrouter-outlet
ディレクティブを使えるようになったのです。
src/app/app-routing.module.tssrc/app/app.module.ts@NgModule({ exports: [RouterModule] }) export class AppRoutingModule {}
@NgModule({ imports: [ AppRoutingModule ], }) export class AppModule {}
03 ルーテイングのリンクを加える
ページのリンクからルーティングできるようにしましょう。親コンポーネント(app.component)のテンプレートに、つぎのように<nav>
要素の中に<a>
要素でリンクを加えます。属性にrouterLink
(RouterLink
)ディレクティブで与えるのが遷移先のパス("/heroines")です。このディレクティブもRouterModule
クラスから提供されます。
src/app/app.component.html<h1>{{title}}</h1> <nav> <a routerLink="/heroines">ヒロインたち</a> </nav>
これで、はじめのページにリンクが加わり、クリックするとリスト表示のコンポーネントが差し込まれます。ブラウザのURLのパスも、ルートから書き替わるはずです。以下のコード001のCSSをコンポーネント(app.component)に定めれば、スタイルが整います(図001)。
図003■リンクをクリックするとリストが表示される
コード001■親コンポーネントのCSSの定め
src/app/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;
}
04 ダッシュボードのコンポーネントを加える
新たにダッシュボードのコンポーネントをつくって、ナビゲーションのリンクに加えましょう。つぎのように、ng generate component
コマンドでコンポーネント(dashboard.component)を生成します。
ngコマンドng generate component dashboard
コンポーネント(dashboard.component)のTypeScriptコードには、つぎのように書き加えてください。クラス(DashboardComponent)の組み立ては、リスト表示のコンポーネントとよく似ています(「Angular 5入門 05」コード002「サービスとリスト表示コンポーネントのTypeScriptコード」参照)。配列のプロパティ(heroines)が定められ、データはメソッド(getHeroines())により納められるかたちです。ただし、Array.slice()
メソッドが件数を4つに絞っています。そして、コンポーネントがつくられたとき、ngOnInit()
からメソッドが呼び出されるのです。
src/app/dashboard/dashboard.component.tsimport {Heroine} from '../heroine'; import {HeroineService} from '../heroine.service'; export class DashboardComponent implements OnInit { heroines: Heroine[] = []; // constructor() { } constructor(private heroineService: HeroineService) { } ngOnInit(): void { this.getHeroines(); } getHeroines():void { this.heroineService.getHeroines() .subscribe(heroines => this.heroines = heroines.slice(0, 4)); } }
コンポーネント(dashboard.component)のテンプレートとCSSファイルは、以下のコード002のとおりです。テンプレートはngFor
ディレクティブで、プロパティ(heroines)の配列要素の数だけ<a>
要素を加えます。リンク先はまだ定められていません。改められたTypeScriptコードも併せて掲げておきます。
コード002■ダッシュボードコンポーネントのコード
src/app/dashboard/dashboard.component.html
<h3>トップヒロイン</h3>
<div class="grid grid-pad">
<a *ngFor="let heroine of heroines" class="col-1-4">
<div class="module heroine">
<h4>{{heroine.name}}</h4>
</div>
</a>
</div>
[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;
}
}
import {Component, OnInit} from '@angular/core';
import {Heroine} from '../heroine';
import {HeroineService} from '../heroine.service';
@Component({
selector: 'app-dashboard',
templateUrl: './dashboard.component.html',
styleUrls: ['./dashboard.component.css']
})
export class DashboardComponent implements OnInit {
heroines: Heroine[] = [];
constructor(private heroineService: HeroineService) { }
ngOnInit(): void {
this.getHeroines();
}
getHeroines():void {
this.heroineService.getHeroines()
.subscribe(heroines => this.heroines = heroines.slice(0, 4));
}
}
05 ナビゲーションにダッシュボードへのリンクを加える
ベージのナビゲーションに、ダッシュボードへのリンクを加えます。リスト表示コンポーネントへのリンクと同じく、つぎのようにルーテイングモジュール(app-routing.module)の定数(routes)に配列要素としてプロパティpath
('dashboard')とcomponent
(DashboardComponent)が与えられたオブジェクトを加えるのです。さらに、空のパス('')つまりURLがルート('/')のときの転送先がredirectTo
プロパティで定められます。これで、はじめにrouter-outlet
ディレクティブの要素が空で示されることはなくなります。なお、pathMatch
プロパティの値'full'
は、パスが完全に空('')のときのみ転送される指定です(「Matching Strategy」参照)。
src/app/app-routing.module.tsimport {DashboardComponent} from './dashboard/dashboard.component'; const routes: Routes = [ {path: '', redirectTo: '/dashboard', pathMatch: 'full'}, {path: 'dashboard', component: DashboardComponent}, ];
あとは、親コンポーネント(app.component)のナビゲーションに、前述で定めたパス("/dashboard")をルーテイングのリンクとして、つぎのようにrouterLink
ディレクティブに与えるだけです。これでアプリケーションをブラウザで開くと、ルートがダッシュボードにリダイレクトされます(図004)。そして、ナビゲーションのリンクで、リスト表示とダッシュボードを切り替えることもできるのです。以下のコード003に、ルーティングのモジュール(app-routing.module)のTypeScriptコードと親コンポーネント(app.component)のテンプレート、およびルーティング(AppRoutingModule)やダッシュボード(DashboardComponent)のクラスが組み込まれたアプリケーション(app.module)のTypeScriptコードをまとめました。Plunkerのサンプルコードは「Angular 5 Example - Tour of Heroines 06」をご覧ください。
src/app/app.component.html<nav> <a routerLink="/dashboard">ダッシュボード</a> <a routerLink="/heroines">ヒロインたち</a> </nav>
図004■はじめにダッシュボードが表示される
コード003■ルーティングのモジュールと親コンポーネントのテンプレートおよびアプリケーションのTypeScriptコード
src/app/app-routing.module.ts
import {NgModule} from '@angular/core';
import {RouterModule, Routes} from '@angular/router';
import {DashboardComponent} from './dashboard/dashboard.component';
import {HeroinesComponent} from './heroines/heroines.component';
const routes: Routes = [
{path: '', redirectTo: '/dashboard', pathMatch: 'full'},
{path: 'dashboard', component: DashboardComponent},
{path: 'heroines', component: HeroinesComponent}
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule {}
<h1>{{title}}</h1>
<nav>
<a routerLink="/dashboard">ダッシュボード</a>
<a routerLink="/heroines">ヒロインたち</a>
</nav>
<router-outlet></router-outlet>
<app-messages></app-messages>
import {BrowserModule} from '@angular/platform-browser';
import {NgModule} from '@angular/core';
import {FormsModule} from '@angular/forms';
import {AppComponent} from './app.component';
import {HeroinesComponent} from './heroines/heroines.component';
import {HeroineDetailComponent} from './heroine-detail/heroine-detail.component';
import {HeroineService} from './heroine.service';
import {MessagesComponent} from './messages/messages.component';
import {MessageService} from './message.service';
import {AppRoutingModule} from './app-routing.module';
import {DashboardComponent} from './dashboard/dashboard.component';
@NgModule({
declarations: [
AppComponent,
HeroinesComponent,
HeroineDetailComponent,
MessagesComponent,
DashboardComponent
],
imports: [
BrowserModule,
FormsModule,
AppRoutingModule
],
providers: [HeroineService, MessageService],
bootstrap: [AppComponent]
})
export class AppModule {}
- Angular 5: Angular CLIで手早くアプリケーションをつくる
- Angular 5入門 01: アプリケーションの枠組みをつくる
- Angular 5入門 02: 編集ページをつくる
- Angular 5入門 03: データのリストを表示する
- Angular 5入門 04: 詳細情報のコンポーネントを分ける
- Angular 5入門 05: データをサービスにより提供する
- Angular 5入門 07: ルーティングで個別情報を示す
- Angular 5入門 08: HTTPサービスでリモートのデータを取り出して書き替える
- Angular 5入門 09: HTTPサービスでリモートのデータを加えたり除いたりする
- Angular 5入門 10: HTTPサービスでリモートのデータを検索する
作成者: 野中文雄
作成日: 2018年1月29日
Copyright © 2001-2018 Fumio Nonaka. All rights reserved.