前回の投稿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
サービスのparams
observable3からの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
サービスのparams
observableから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()メソッド@アルファシス ↩