AngularJS TIPS
URL経由でパラメーター情報を引き渡すには?($routeProviderプロバイダー)
ngRouteモジュールを使ったAngularJSのルーティングで、URL経由でパラメーター情報を引き渡す方法を解説する。
別稿「TIPS:ルーティング機能を実装するには?」では、ngRoute
モジュールを利用したルーティング機能の実装について解説しました。本稿では、引き続きルーティング機能を利用して、URL経由でパラメーター情報を引き渡す方法を解説します。
この機能を利用することで、例えば「~/contents/10」のようなURLにアクセスすると、ルートパラメーターid
に対して10という値がセットされるようになります。ルートパラメーターには、コントローラーなどからアクセスできますので、一般的には、その情報をキーとして、サーバーサイドから具体的なコンテンツを取得することになるでしょう。
では、以下に具体的なコードを見ていきます。基本となるサンプルは、前掲の別稿で解説したものを利用しますので、全体のコードはそちらを併せて参照してください。
ルーティング情報の定義
ルートパラメーターを受け取れるようにするには、まず、$routeProvider
プロバイダーのwhen
メソッドで、URLパターンを修正します。
angular.module('myApp', [ 'ngRoute' ])
.config(['$routeProvider', function($routeProvider){
$routeProvider
.when('/', {
templateUrl: 'views/home.html',
controller: 'HomeController'
})
.when('/contents/:id', {
templateUrl: 'views/contents.html',
controller: 'ContentsController'
})
……中略……
});
}]);
|
:名前
の形式で表されているのは、ルートパラメーターのプレイスホルダーです。マッチしたURLに応じて、対応する値がルートパラメーターにセットされます。従って、「~/contents/10」であればid
は10になりますし、「~/contents/hoge」であればid
はhogeとなります。
ここでは、ルートパラメーターを1つだけ定義していますが、例えば「/contents/:category/:id」のようにすることで、複数のパラメーター(この場合はcategory
/id
)を埋め込むこともできます。
ルートパラメーターを受け取る方法
ルートパラメーターを受け取るには、$routeParams
サービスを利用します。以下のように、コントローラーに依存性注入した上で、$routeParams.名前
の形式でアクセスします。
angular.module('myApp')
……中略……
.controller('ContentsController', ['$scope', '$routeParams', function($scope, $routeParams) {
$scope.id = $routeParams.id;
}])
|
<div>
<h1>個別記事</h1>
<p>連載 第{{id}}回</p>
</div>
|
……前略……
<ul>
<li><a ng-href="#/home">ホーム</a></li>
<li><a ng-href="#/contents/10">記事を読む</a></li>
<li><a ng-href="#/tags/angular/javascript/jquery">関連記事を検索</a></li>
</ul>
……後略……
|
さまざまなルートパラメーター
プレイスホルダーに「?」「*」などの記号を付与することで、省略可能なパラメーター、可変長パラメーターを表現することもできます。
1省略可能なパラメーター
先ほどの例では、「~/contents/10」「~/contents/hoge」のようなURLにはマッチしますが、「~/contents/」にはマッチしません。デフォルトでは、ルートパラメーターid
が必須であるからです。
もしも「~/contents/」――:id
パラメーターの省略を許容したい場合には、ルートパラメーターの後方に?
を付与します。例えば以下のようにです。
.when('/contents/:id?', {
templateUrl: 'views/contents.html',
controller: 'ContentsController'
})
|
また、ルートパラメーターを省略可能にした場合、一般的にはコントローラー側で省略時の挙動を明確にしておくべきでしょう。例えばここでは、スコープ変数id
に「-」を設定します。
.controller('ContentsController', ['$scope', '$routeParams', function($scope, $routeParams) {
$scope.id = $routeParams.id ? $routeParams.id : '-';
}])
|
この状態で、「~/contents/」にアクセスすると、確かに以下のような結果が得られるはずです。
2可変長パラメーター
「:list*」のように、名前の後方に*
を付与することで、「/」をまたいで、以降のパスを1つの変数にまとめることもできます。
例えば以下のようなURLパターンを設定した場合、URL「~/tags/angular/javascript/jquery」に対するルートパラメータlistの値は「angular/javascript/jquery」となります。
.when('/tags/:list*', {
templateUrl: 'views/tags.html',
controller: 'TagsController'
})
|
.controller('TagsController', ['$scope', function($scope) {
$scope.list = $routeParams.list;
}]);
|
<div>
<h1>タグ{{list}}による検索</h1>
<p>...検索結果...</p>
</div>
|
$routeParams
の戻り値は(配列などではなく)「/」区切りの文字列である点に注意してください。実際に利用する際には、手元で分割などする必要があるでしょう。
ルートの優先順位
複雑なパターンを指定するようになると、ルートを追加する順序にも気を付ける必要があります。ルートは追加された順に判定され、複数のルートにマッチする場合には最初にマッチしたものが優先されるからです。
例えば以下のような順序で定義されたルートは、正しく動作しません。
/:group/:id
/contents/:id
この場合、例えば「~/contents/13」のようなリクエストがあっても、1のルートにまずマッチしますので(group
=contents、id
=13、です)、2のルートにマッチすることはありません。
ルートを追加する際には、必ず「特殊なルートを先に、より汎用的なルートを後に」定義してください。
処理対象:ルーティング(ngRoute) カテゴリ:基本
API:$routeProvider カテゴリ:ngRoute > provider(プロバイダー)
API:$routeParams カテゴリ:ngRoute > service(サービス)
※以下では、本稿の前後を合わせて5回分(第49回~第53回)のみ表示しています。
連載の全タイトルを参照するには、[この記事の連載 INDEX]を参照してください。
49. AngularJSを手動で起動するには?(bootstrap)
通常は自動起動するAngularJSを手動で起動するにはangular.bootstrapメソッドを使用する。その基本的な使い方を解説。
50. ルーティング機能を実装するには?($routeProviderプロバイダー)
AngularJSではngRouteモジュールを利用したルーティングが可能だ。その基本的な用法(ルーティングの定義/コントローラー/テンプレートなど)について解説する。
51. 【現在、表示中】≫ URL経由でパラメーター情報を引き渡すには?($routeProviderプロバイダー)
ngRouteモジュールを使ったAngularJSのルーティングで、URL経由でパラメーター情報を引き渡す方法を解説する。
52. ルーティングの挙動/設定をカスタマイズするには?($routeProviderプロバイダー)
「テンプレートを文字列で指定(templateパラメーター)」「リダイレクト時の規則をカスタマイズ(redirectToパラメーター)」「html5モードに切り替える」という、特によく使われる3つのカスタマイズ方法を取り上げる。
53. 配列/オブジェクトをコピーするには?(copy)
配列のコピーで、JavaScript標準のconcatメソッドを使う場合とAngularJSのcopyメソッドを使う場合の違いを説明。シャローコピーとディープコピーとは?