前回の投稿Angluar2のクイックスタートとチュートリアルを実施 - その5の続きです。
前回作成したソースを使用します。
本章ではルーティング(=画面遷移)を学びます。ナビゲーションとも呼びます。ビューからビューへの移動を定義します。
本章は結構長いです...
本投稿の参照元(英語)
本章で学ぶこと
前述のほか、以下を学びます。
- ダッシュボード1ビューを追加する
- ルーターによりヒーロー一覧とダッシュボードビューを切り替える
-
HeroServiceを複数コンポーネントで共有する - htmlとcssを外部ファイルに移動する
- パイプ
uppercaseの使い方を学ぶ
ナビゲーションのイメージは以下です。(公式より拝借)
実行結果
本章を完了すると以下リンク先のようなものが出来上がります。
尚、右上の青いボタンを押すことで全画面表示を行うことができます。
上図の実際の動きがわかります。
live-examples
事前準備
以下のコマンドによりサーバの起動を行います。プログラムの変更が即座にブラウザに反映されます。(サーバを落としていなければ不要です。)
cd angular2-tour-of-heroes
npm start
参考
公式のRouting and Navigation(英語)では、本章についてのより詳細な情報が記載されています。
計画
以下の計画に沿って実施します
-
AppComponentの役割をナビゲーションのハンドルだけにする - ヒーロー一覧を
AppComponentからHeroesComponentに移す - ルーティングを作成する
-
DashboardComponentを作成する - ダッシュボードにナビゲーション構造を持たせる
AppComponentを分割
現在はAppComponentをロードするとヒーロー一覧を即座に表示しますが、画面の遷移を行うシェルにし、その他のことは他のコンポーネントにまかせます。
AppComponentクラスからヒーロー一覧をHeroesComponentに移動させましょう。
HeroesComponent
AppComponentは既にヒーロー一覧用のプログラムなので、そのままHeroesComponentに変更します。以下のリネームを実施します。
| 種別 | 変更前 | 変更後 |
|---|---|---|
| ファイル名 | app/app.component.ts |
app/heroes.component.ts |
| クラス名 | AppComponent |
HeroesComponent |
@Componentデコレータのselector
|
my-app |
my-heroes |
新しいAppComponent
新しいapp/app.component.tsはアプリケーションシェルにします。いくつかのコンポーネントへのリンクを画面上部に表示し、ページへナビゲートします。まず以下を行います。
-
app/app.component.tsファイルを作成する -
app/app.component.tsでやること・・・-
AppComponentクラスの定義 -
@Componentデコレータとmy-appセレクタの追加 -
HeroesComponentからAppComponentへ以下を移動させる-
titleクラスプロパティ -
@Componentのテンプレートの<h1>要素。これは、titleのバインドを含む
-
-
@Componentのテンプレートに<my-heroes>要素を追加し、ヒーロー一覧を表示
させる -
Componentのインポート
-
-
app/app.module.tsでやること・・・-
@AppModuleのdeclarations配列にHeroesComponentを追加し<my-heroes>タグを使用可能にする -
@AppModuleのprovidersにHeroServiceを追加
-
-
app/heroes.component.tsでやること・・・-
@Componentのprovidersを削除
-
結果app/app.component.ts, app/app.module.tsは以下の様になります。
import { Component } from '@angular/core';
@Component({
selector: 'my-app',
template: `
<h1>{{title}}</h1>
<my-heroes></my-heroes>
`
})
export class AppComponent {
title = 'Tour of Heroes';
}
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
import { AppComponent } from './app.component';
import { HeroDetailComponent } from './hero-detail.component';
import { HeroesComponent } from './heroes.component';
import { HeroService } from './hero.service';
@NgModule({
imports: [
BrowserModule,
FormsModule
],
declarations: [
AppComponent,
HeroDetailComponent,
HeroesComponent
],
providers: [
HeroService
],
bootstrap: [ AppComponent ]
})
export class AppModule {
}
この段階でもまだアプリケーションは動作します。リファクタリングによる問題はおきません。
ベースタグの追加
index.htmlの<head>セクションの下に<base href="/">タグを追加します。
<head>
<base href="/">
base hrefは必要です。理由はRouter#base-href(英語)に記載があります。
ルーティングの追加
今まで、自動的にヒーロー一覧を表示していた代わりに、ボタンをクリックしたら表示するように変更します。これには_コンポーネントルーター_を使用します。
Angularのルーターは外側におり、オプションモジュールで、RouterModuleと呼ばれます。
ルーターは複数の提供サービス(RouterModule)と、複数のディレクティブ(RouterOutlet, RouterLink, RouterLinkActive)と、設定ファイル(Routes)の組み合わせからなります。最初に行うのは設定です。
route2の設定
まだこのアプリは何のrouteも設定していません。コンフィグファイルを作りアプリケーションrouteを設定します。
_Routes_はユーザがボタンをクリックしたり、URLを貼り付けたときに、どのビューを表示するかをルーターに伝えます。
app/app.routing.tsファイルを作成し、HeroesComponentへのrouteを定義します。
import { ModuleWithProviders } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { HeroesComponent } from './heroes.component';
const appRoutes: Routes = [
{
path: 'heroes',
component: HeroesComponent
}
];
Routesはroute定義の配列です。現在routeはHeroesComponetへの一つだけしかないですが後で追加します。_route_の定義は以下からなります。
- path: routerがこのパスとブラウザのURLの一致を確認する(この場合
heroes) - component: このrouteにナビゲートされたときルーターが作成するコンポーネント (この場合
HeroesComponent)
Routesの詳細は、公式のRouting(英語)にあります。
routing定数を宣言し、他で使用できるようにエクスポートします。この値はRouterModule.forRootメソッドの戻り値です。このメソッドはroutesを引数に、configured router moduleを返します。AppModuleの@NgModuleにそれを追加します。
export const routing: ModuleWithProviders = RouterModule.forRoot(appRoutes);
forRootと呼ばれる理由は、アプリケーションroot(AppModule)用のルーターを提供するためです。forRootメソッドはルーターサービスのプロバイダーとディレクティブを返します。これらはルーティングに使用します。
利用可能なルーターの作成
app/app.routing.tsに初期設定をしました。rootモジュールのNgModuleにそれを追加しましょう。routing定数をapp.routing.tsからインポートし、AppModule のimports配列に追加します。
import { routing } from './app.routing';
@NgModule({
imports: [
BrowserModule,
FormsModule,
routing
],
})
export class AppModule {
}
Router Outlet(ルーターの出口)
ブラウザのアドレスバーに/heroesを入れるとHeroesComponentを表示しますが、ページのどこに表示するかは、テンプレートの<router-outlet>要素によって定めます。
RouterOutletはRouterModuleにより提供されるディレクティブの一つです。
ルーターは各コンポーネントを<router-outlet>の場所に表示します。
Router Links(ルーターリンク)
アプリ利用者により、route URLをアドレスバーに貼り付けられることを想定していません。テンプレートにアンカータグを追加することで、クリックされた際にHeroesComponentへナビゲートします。
template: `
<h1>{{title}}</h1>
<a routerLink="/heroes">Heroes</a>
<router-outlet></router-outlet>
`
routerLinkは、アンカータグにバインドされています。RouterLinkディレクティブはリンクをクリックしたとき、指定した文字列(ここでは/heroes)がどこへナビゲートするかをルーターへ伝えます。
直接のリンクをやめたため、ルートパスへルーティング指示をワンタイムバインディングとして定義します。route設定をもう一度確認してください。'/heroes'をHeroesComponentへ通しています。
公式のRouting#link-parameters-array(英語)で、直接のルーターリンクや、リンクパラメータ配列について学べます。
ブラウザを更新すると、タイトルとheroesリンクだけになり、ヒーロー一覧が見えなくなります。
現在、ブラウザーのアドレスバーは/を指定しています。HeroesComponentを表示するのは/heroesなので何も見えません。後で対応します。アドレスを/heroesに変えれば、ヒーロー一覧が表示されます。
本項により、AppComponentは以下の様になりました。
import { Component } from '@angular/core';
@Component({
selector: 'my-app',
template: `
<h1>{{title}}</h1>
<a routerLink="/heroes">Heroes</a>
<router-outlet></router-outlet>
`
})
export class AppComponent {
title = 'Tour of Heroes';
}
AppComponentは、ルーターとrouteされたビューが結びつけられました。このようなコンポーネントを_ルーターコンポーネント_と呼びます。
ダッシュボード1の追加
ルーティングは複数のビューがあってこそ意味をなします。新しいビューを作ります。
app/dashboard.component.tsを以下の様に作成します。
import { Component } from '@angular/core';
@Component({
selector: 'my-dashboard',
template: '<h3>My Dashboard</h3>'
})
export class DashboardComponent { }
後で役に立つように変更します。
ダッシュボードのroute設定
ダッシュボードのビューが表示されるように、app/app.routing.tsにRoutesに定義を追加します。
{
path: 'dashboard',
component: DashboardComponent
},
rootモジュールであるAppModuleクラスNgModuleのdeclarations配列に、DashboardComponentを追加します。
declarations: [
AppComponent,
DashboardComponent,
HeroDetailComponent,
HeroesComponent
],
リダイレクトの設定
アプリケーションの開始時にアドレスバー/dashboardを表示し、ダッシュボードを表示します。これにはリダイレクトを使用します。
以下の様にapp/app.routing.tsを変更します。
{
path: '',
redirectTo: '/dashboard',
pathMatch: 'full'
},
リダイレクトについての詳細は、公式のRouter(英語)にあります。
テンプレートにナビゲーションを追加
最後に、ヒーロー一覧より前に、ダッシュボードのリンクを追加します。
template: `
<h1>{{title}}</h1>
<nav>
<a routerLink="/dashboard">Dashboard</a>
<a routerLink="/heroes">Heroes</a>
</nav>
<router-outlet></router-outlet>
リンクを<nav>タグ内に記載していますが、今は何も機能しません。後でスタイルを追加するときに便利なのでタグを記載します。
ブラウザで、アプリケーションroot(/)を表示するとダッシュボードが表示され、ダッシュボードとヒーロー一覧へのリンクが表示されます。
ダッシュボードのトップヒーロー一覧
dashboard.component.tsのhtmlテンプレートを外部テンプレートファイルに変更します。以下の様にtemplateの部分をtemplateUrlに変更してください。
ファイル名はapp/dashboard.component.htmlとします。
templateUrl: 'app/dashboard.component.html',
なお、Angularでは相対パスはサポートしていませんので、アプリケーションルートからの絶対パスでURLを指定する必要があります。(今回の場合app/dashboard.component.html)
中身を以下の様に定義します。
<h3>Top Heroes</h3>
<div class="grid grid-pad">
<div *ngFor="let hero of heroes" (click)="gotoDetail(hero)" class="col-1-4">
<div class="module hero">
<h4>{{hero.name}}</h4>
</div>
</div>
</div>
もう一度、ヒーロー一覧のイテレートのために*ngForを使用しヒーロー名を表示します。本章の後でスタイルを追加するために、<div>を入れています。
また、(clock)にバインドしているgotoDetail()メソッドも後で追加します。
ヒーローサービスの共有
ダッシューボードがヒーロー情報を取得するためにHeroServiceを再利用します。
本章の序盤でHeroServiceをHeroesComponentのプロバイダからAppModuleのプロバイダに移動しました。これにより、すべてのコンポーネントでシングルトンインスタンスのHeroServiceを使うことができます。
ヒーローの取得
app/dashboard.component.tsのインポート記載部分を以下の様にします。
import { Component, OnInit } from '@angular/core';
import { Hero } from './hero';
import { HeroService } from './hero.service';
また、DashboardComponentを以下の様に実装します。
export class DashboardComponent implements OnInit {
heroes: Hero[] = [];
constructor(private heroService: HeroService) { }
ngOnInit(): void {
this.heroService.getHeroes()
.then(heroes => this.heroes = heroes.slice(1, 5));
}
gotoDetail(hero: Hero): void { /* まだ実装しない */}
}
HeroesComponentと同じ様なものですが、ヒーロー一覧から4人(2番目〜5番目)を取得しているところと、スタブgotoDetailを用意しているところが異なります。
ブラウザ上で4人のヒーローが表示されていることを確認できます。
ヒーロー詳細への画面遷移
HeroesComponentの下に表示していたヒーロー詳細ですが、現在3つの方法で詳細を表示する必要があります。
- ダッシュボードから選択したヒーロー
- ヒーロー一覧から選択したヒーロー
- URLから直接入力されたもの
ヒーロー詳細へのルートを個別の場所に表示する様に追加します。
ヒーロー詳細へのroute
app/app.routing.tsにHeroDetailComponentへのrouteを追加します。
新しいrouteはちょっと普通と違う方法をとります。HeroDetailComponentを使用しますが、呼び出し元のHeroesComponentにもDashboardComponentにも呼び出す方法を持っていません。現在HeroesComponentがheroプロパティをセットする場合以下のようにバインドしています。
<my-hero-detail [hero]="selectedHero"></my-hero-detail>
これは明白にほかのシナリオでは動きません。
routeの調整
URLで、ヒーローのidを以下のように指定することで実現します。
/detail/11
detailは定数です。数字部分は変数で、このパラメータをヒーローのidとするルートが必要です。
Routeの設定
以下の様にrouteを定義します。
{
path: 'detail/:id',
component: HeroDetailComponent
},
:idのコロンはプレースホルダーでHeroDetailComponentへ遷移させるときヒーローのidとして使用します。
これで、アプリケーションのrouteの作成は完了です。
'Hero Detail'からのテンプレートへのリンクは作成しません。なぜなら、利用者は特定のヒーローへのナビゲーションはクリックしないからです。利用者は、ダッシュボードか、ヒーロー一覧をクリックします。
後の項で、ヒーローをクリックしたときの動きを取得します。
HeroDetailComponentの修正
HeroDetailComponentを書き換えます。
import { Component, Input } from '@angular/core';
import { Hero } from './hero';
@Component({
selector: 'my-hero-detail',
template: `
<div *ngIf="hero">
<h2>{{hero.name}} details!</h2>
<div>
<label>id: </label>{{hero.id}}
</div>
<div>
<label>name: </label>
<input [(ngModel)]="hero.name" placeholder="name"/>
</div>
</div>
`
})
export class HeroDetailComponent {
@Input() hero: Hero;
}
テンプレート部分は変更しません。大きな変更点はどうやってヒーローを取得するかの部分です。もう、親のコンポーネントからヒーロー情報を取得することをやめ、新しいHeroDetailComponentはActivatedRouteサービスのparamsobservable3からのidパラメータとHeroServiceのidから取得したheroを使います。
まず、必要なものをインポートします
// まだ、Inputは残しますが, 後で消します。
import { Component, Input, OnInit } from '@angular/core';
import { ActivatedRoute, Params } from '@angular/router';
import { HeroService } from './hero.service';
コンストラクタに、privateなActivatedRouteサービスとHeroServiceサービスを定義します。
constructor(
private heroService: HeroService,
private route: ActivatedRoute) {
}
HeroDetailComponentクラスにOnInitインタフェースを実装します。
export class HeroDetailComponent implements OnInit {
ngOnInitライフサイクルフック内で、ActivatedRouteサービスのparamsobservableからidパラメータを取り出しHeroServiceでidからヒーローを取得します。
ngOnInit(): void {
this.route.params.forEach((params: Params) => {
let id = +params['id'];
this.heroService.getHero(id)
.then(hero => this.hero = hero);
});
}
forEachメソッドによりidを取得しています。forEachはrouteパラメータ配列を提供します。idは数値型(number)です。routeパラメータは通常、文字列型(string)です。Javascriptの(+)演算子により、routeパラメータを数値型に型変換しています。
ヒーローサービスクラスへgetHero()メソッドの追加
HeroServiceにgetHero()メソッドを追加します。getHero()メソッドでは、getHeroes()メソッドで取得したヒーロー一覧をidでフィルタします。
getHero(id: number): Promise<Hero> {
return this.getHeroes()
.then(heroes => heroes.find(hero => hero.id === id));
}
画面の戻りかた
複数の方法でHeroDetailComponentへ画面遷移できますが他への遷移はどうやるのでしょうか。
AppComponentから二つのリンクをクリックできます。また戻るボタンでも移動できます。第三の方法としてgoBackメソッドにより、ブラウザのヒストリースタックを使用して戻る方法4があります。
goBack(): void {
window.history.back();
}
アプリケーション外まで戻ることは、このチュートリアルでは許容していますが、実際のアプリでは抑止したいものです。CanDeactivate guard(英語)で方法が学べるはずです。
goBack()メソッドをコンポーネントのテンプレートに以下の様に追加し、バインドします。
<button (click)="goBack()">Back</button>
この追加したボタンと一緒に、ヒーロー詳細を表示するテンプレートを別ファイルapp/hero-detail.component.htmlに移します。
<div *ngIf="hero">
<h2>{{hero.name}} details!</h2>
<div>
<label>id: </label>{{hero.id}}</div>
<div>
<label>name: </label>
<input [(ngModel)]="hero.name" placeholder="name" />
</div>
<button (click)="goBack()">Back</button>
</div>
app/hero-detail.component.ts側はテンプレートからテンプレートURLに変更し、htmlファイルを読み込みます。
templateUrl: 'app/hero-detail.component.html',
ブラウザを更新し、結果を確認してください。
ダッシュボードからヒーローを選択する
ダッシュボードからヒーローが選択されたとき、ヒーロー詳細を表示/編集可能にするべきです。ダッシュボードのテンプレートでは各ヒーローをクリックするとgotoDetail()メソッドを呼び出します。
<div *ngFor="let hero of heroes" (click)="gotoDetail(hero)" class="col-1-4">
スタブ化していたgotoDetail()を今、実装します。
gotoDetail(hero: Hero): void {
let link = ['/detail', hero.id];
this.router.navigate(link);
}
gotoDetailメソッドは以下の2ステップにより画面遷移します。
- _link_配列にrouteパラメータを格納
-
routerのnavigateメソッドにそれを渡す
画面遷移を行うために以前AppComponentのテンプレートにルーターリンクを実装しました。これらのリンクは一つの要素のみ持ちますが、今回のパラメータ配列は2つの要素を持ちます。目的のrouteのpathとヒーローのidをセットするroute parameterです。
この二つのアイテムpathと:idは以前、app.routing.tsにパラメータ化しています。
{
path: 'detail/:id',
component: HeroDetailComponent
},
DashboardComponentはまだルーターを持っていません。インポートしてコンストラクタに登録します。
import { Router } from '@angular/router';
constructor(
private router: Router,
private heroService: HeroService) {
}
ブラウザを更新しダッシュボードからヒーローを選択すると、ヒーロー詳細に画面遷移します
HeroesComponentからのヒーローの選択
HeroesComponentにも同じ様に実装します。
このコンポーネントは現在、"マスター/ディティール"の形式(一覧と詳細)をとっています。
template: `
<h1>{{title}}</h1>
<h2>My Heroes</h2>
<ul class="heroes">
<li *ngFor="let hero of heroes"
[class.selected]="hero === selectedHero"
(click)="onSelect(hero)">
<span class="badge">{{hero.id}}</span> {{hero.name}}
</li>
</ul>
<my-hero-detail [hero]="selectedHero"></my-hero-detail>
`,
<h1>タグを削除します。AppComponentからHeroesComponentに変更したときのごみです。次に<my-hero-detail>タグも削除します。もうここにはヒーロー詳細を表示しません。ヒーロー詳細は専用のページを用意し、ダッシュボードと同様、そのページへのrouteを作ります。
ここでちょっとひねった方法をとります。ヒーロー一覧からヒーローを選択しても、すぐにはヒーロー詳細を表示せずに、まずはミニ詳細を代わりに表示し、ミニ詳細に表示されたボタンをクリックすることで、フルの詳細ページに移動するようにします。
ミニ詳細の追加
<my-hero-detail>の場所に以下のhtmlの一部を追加します。
<div *ngIf="selectedHero">
<h2>
{{selectedHero.name | uppercase}} is my hero
</h2>
<button (click)="gotoDetail()">View Details</button>
</div>
ヒーロークリックにより、以下の様なものがヒーロー一覧の下に表示されます。
パイプによる大文字変換
パイプ演算子(|)とuppercaseパイプにより表示文字を大文字に変更できます。
{{selectedHero.name | uppercase}} is my hero
パイプは「文字列のフォーマット」「通貨単位」「日付」などを表示するには、いい方法です。Angularにはいくつかのパイプと書き方が用意されています。
詳細は公式のPipes(英語)に記載されています。
コンポーネント外に内容を移す
まだミニ詳細の[View Details]ボタンを押したときにHeroDetailComponentへ画面遷移する機能に対応していませんが、ヒーロー一覧コンポーネントは非常に大きく、ほとんどはcss部分です。htmlとcssを他のファイルに移動します。
以下のマイグレーションを行います。
- htmlテンプレート部分を
app/heroes.component.htmlにカット&ペースト - スタイル部分を
heroes.component.cssにカット&ペースト -
@ComponentデコレータにtemplateUrlとstyleUrlsプロパティを追加し、それぞれのファイルパスを記載
styleUrlsプロパティは、スタイルシートのファイルパスの配列です。必要に応じ複数のスタイルを適用できます。
@Component({
selector: 'my-heroes',
templateUrl: 'app/heroes.component.html',
styleUrls: ['app/heroes.component.css']
})
ダッシュボードと同じ様にコンポーネントクラスを更新します
-
routerをインポート - コンストラクタで
routerをインジェクト -
router.navigateメソッドに呼ばれるgotoDetailメソッドの実装
app/heroes.component.tsは以下の様に修正されます。
export class HeroesComponent implements OnInit {
heroes: Hero[];
selectedHero: Hero;
constructor(
private router: Router,
private heroService: HeroService) { }
getHeroes(): void {
this.heroService.getHeroes().then(heroes => this.heroes = heroes);
}
ngOnInit(): void {
this.getHeroes();
}
onSelect(hero: Hero): void {
this.selectedHero = hero;
}
gotoDetail(): void {
this.router.navigate(['/detail', this.selectedHero.id]);
}
}
ブラウザを更新しクリックするとナビゲートできるようになります。ダッシュボードから、詳細へいったり、ダッシュボードに戻ったり、ヒーロー一覧から、ミニ詳細を通して、ヒーロー詳細を表示したり、ヒーロー一覧へ戻ったりができます。
本章の機能の実現は以上です。
アプリケーションのスタイル
機能は実現できましたが、見た目がイマイチです。cssを変更します。
ダッシュボードのスタイル
app/dashboard.component.tsの@Componentデコレータに以下を追加します。
styleUrls: ['app/dashboard.component.css']
洒落たヒーロー詳細
DashboardComponentからheroプロパティ、@Inputデコレータとそれらをインポートしているインポート句を削除し、以下の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;
}
[class*='col-'] {
float: left;
}
*, *:after, *:before {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
h3 {
text-align: center; margin-bottom: 0;
}
[class*='col-'] {
padding-right: 20px;
padding-bottom: 20px;
}
[class*='col-']:last-of-type {
padding-right: 0;
}
.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;
}
h4 {
position: relative;
}
.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;
}
}
ナビゲーションリンクのスタイル
AppComponentの<nav>タグにもスタイルを適用します。
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;
}
_routerLinkActive_ディレクティブ
Angularでは、routerLinkActiveディレクティブが提供されています。htmlナビゲーション要素に追加することでrouteがアクティブなrouteになったときのcssが定義できます。
template: `
<h1>{{title}}</h1>
<nav>
<a routerLink="/dashboard" routerLinkActive="active">Dashboard</a>
<a routerLink="/heroes" routerLinkActive="active">Heroes</a>
</nav>
<router-outlet></router-outlet>
`,
AppComponentもstylesプロパティからstyleUrlsプロパティに変更します。
styleUrls: ['app/app.component.css'],
グローバルアプリケーションスタイル
アプリケーションの外へスタイルを作成できます。
ベーシックなスタイルをアプリに適用する場合、クイックスタートのスタイルシートの追加で紹介した方法を用います。
/* Master Styles */
h1 {
color: #369;
font-family: Arial, Helvetica, sans-serif;
font-size: 250%;
}
h2, h3 {
color: #444;
font-family: Arial, Helvetica, sans-serif;
font-weight: lighter;
}
body {
margin: 2em;
}
body, input[text], button {
color: #888;
font-family: Cambria, Georgia;
}
/* . . . */
/* everywhere else */
* {
font-family: Arial, Helvetica, sans-serif;
}
スタイルシートの全文は公式のこちらです。
必要に応じてindex.htmlをスタイルシートを参照する様に変更します。
<link rel="stylesheet" href="styles.css">
現在の見た目は以下の様になります。
本章は以上です。まだこのアプリでは、リモートデータアクセスを実装していません。次章ではモックデータを置換し、httpを使ってデータを取得する方法の説明を行います。
-
ダッシュボードとは「複数の情報源からデータを集め、概要をまとめて一覧表示する機能や画面、ソフトウェアのこと。」らしいです。IT用語辞典 @e-words ↩ ↩2
-
ルートと書くと、rootなのかrouteなのか分かりづらいのでアルファベットで記載します。root=根、route=道です。一応。 ↩
-
Javascriptのリファレンスを確認してください。window.history.back()メソッド@アルファシス ↩


