Angluarでルーターを使う
はじめに
この記事では、次の2つのビューをAngularのルーター機能で切り替える例を紹介します。ルーターはURLにより自動的に設定されたビューを表示します。以下のように画面の上部にボタンを設置し、これらを切り替える例を説明していきます。
修正するファイルと新規に作成するファイルを以下の表に記します。ファイル名をクリックするとダウンロードできます。
役割 | URL | 区分 | ファイル名 (src/app以下) |
備考 |
デフォルトビュー | / | 修正 | app.component.ts | 階層のトップ |
メインビュー | /main | 新規 | main.component.ts main.component.html |
タイトルを表示 |
設定ビュー | /setting | 新規 | setting.component.ts setting.component.hml |
タイトルを設定 |
ルーター設定ファイル | N/A | 修正 | app.module.ts | URLとビューの対応を追加 |
共有データサービス | N/A | 新規 | data.service.ts | タイトルの文字列を保持 |
プロジェクトの作成
ngコマンドでapp2という名前のプロジェクトを作ります。(Angularのインストール方法についてはこちらの記事を参照)
$ ng new app2
$ cd app2; npm start
以下では、表に示した項目について説明していきます。
デフォルトビュー
app.component.tsには特段、記述すべきことがらはありません。ページの構造は次のapp.component.htmlに記載されています。nav要素の中にrouterLink属性で/mainと/settingへのリンク (に相当するもの) を定義しています。一番下のrouter-outlet要素の部分は、URLに応じて、以下で説明するメインビュー、または、設定ビューが展開されます。URLと各ビューとURLの対応は、app.module.tsで行われています。
<nav>
<a routerLink="/main">Main</a>
<a routerLink="/setting">Setting</a>
</nav>
<router-outlet></router-outlet>
画面のイメージは次のとおりです。nav要素の部分が青い四角、router-outletの部分が緑色の四角に対応します。
メインビュー
main.component.tsでポイントになるのは、MainComponentクラスのコンストラクターでDataServiceクラスの変数を定義していることです。このDataServiceクラスは、その名のとおり、Angularのサービスです。
constructor(private data: DataService) {
サービスは、プロジェクト全体を通じて共有されるデータや機能です。本プロジェクトの場合、設定ビューで入力されるデータ(タイトル名)をメインビューに渡す必要があります。この目的のためにサービスを使用しています。サービスといっても、この例ではデータを定義した以下のクラスの単なるインスタンスです。インスタンスが作成されたときに実行されるconstructor()を除けば、変数titleを一つ含むだけです。なお、constructorは、この例では本質的には不要ですが、実行の流れをわかりやすくするためにメッセージを出力しています。
export class DataService {
title: string = "Untitled";
constructor() {
console.log("DataService: constructor");
}
}
データを共有するためには、当然ですがインスタンスは1つでなければなりません。そのインスタンスを生成するためにInjectorというAngularの機能を使用します。具体的には、app.module.tsに以下を記述します。
providers: [DataService],
ビューに話を戻します。ビューのテンプレートはmain.component.htmlに記述されています。以下のようにh1要素で、サービスとして定義したデータ構造の中の文字列 (title) を表示するだけです。{{ }}は、対応するコンポーネントの中の変数data.titleをDOMとして表示するAngularの記法です。Angularの公式ドキュメントでは、この機能をinterpolationと呼んでいます。
<h1>
{{data.title}}
</h1>
設定ビュー
setting.component.tsのSettingComponentクラスでも共有データを使用するために、constructorでDataServiceクラスのサービスを定義しています。
export class SettingComponent {
constructor(private data: DataService)
実際にdataを使用するのは、HTMLテンプレートsetting.component.htmlです。
<div class="setting">
<label>title</label>
<input [(ngModel)]="data.title"/>
</div>
[(ngModel)]は、Two-way data bindingと呼ばれる機能で、DOM (この場合、input要素) の内容がユーザーによって変更された場合、それがコンポーネント内の変数data.titleに反映され、また、コンポーネント側の変数が変更された場合にも、DOMに反映されます。公式ドキュメントの次の図は、これらの関係を分か易く示しています。
ルーターの設定
ルーティングについては、app.module.tsで設定します。次のようにURLのパスと実際に使用するコンポーネントを定義します。
const routes: Routes = [
{ path: '', redirectTo: '/main', pathMatch: 'full' },
{ path: 'main', component: MainComponent },
{ path: 'setting', component: SettingComponent },
];
それをRuterModuleをインポートする際のパラメータとして渡します。
@NgModule({
(略)
imports: [
(略)
RouterModule.forRoot(routes),
],
これで、app.component.htmlの<router-outlet>要素が意図通りに機能するようになります。
ブラウザでの表示確認
実際に表示させてみましょう。実行順をわかりやすくするために、JavaScriptコンソールも表示しています。まず、ブラウザでhttp://localhost:4200にアクセスします。すると、以下の画像のように/mainにリダイレクトされます。これは、app.modules.tsの中でそのように設定しているからです。DataServiceクラスのtitle変数の初期値がUntitledなので、タイトル文字列にはそれが表示されています。
上部のSettingをクリックすると以下の画面に遷移します。URLのパス部分は/settingになっています。input要素には、タイトルのUntitledがセットされています。
ここで、Untitledを以下のようにMIRACLEに変更してみます。
そして、上部のMainをクリックします。すると、次のように入力文字列が反映されていることがわかります。
また、JavaScript Consoleに着目すると、メインビューに戻ると再度MainComponentのconstructorが呼ばれています。一方、DataServiceのコンストラクタは1度しか呼ばれていません。すなわち、画面が変わっても保持したいデータはそのままであることがわかります。
関連情報
この記事は、公式チュートリアルをよりシンプルにしたものです。こちらには、さらに実用的な例が掲載されていますので、必要に応じてそちらも参照ください。