ngRouteモジュールにおけるルーティングとは
ngRouteでは、HTMLのテンプレートとコントローラをURLのパターンによって管理することができます(図2)。
また、ngRouteではHTML5におけるHistory APIやそれと同様の機能により、ブラウザバックやURLによるページ遷移も実際のサーバへのリクエストをせずに行うことができます。このため、SPAで生じやすい問題に対して特別の対策を行うことなくアプリケーションが開発できます。また、ソースの構造がルール化しやすいので複数の開発者による開発が行いやすくなります。
History APIとは
History APIはブラウザのURLの履歴に関するAPIです。例えば、ブラウザでの戻る(ブラウザバック)・進むボタンを押したときと同様の事をする処理などはHTML5以前でも使えますが、
HTML5ではそれらの履歴に任意のURLを追加したり、また、URLが変わったときにイベント処理を行ったりすることも可能です。
ngRouteサービスはAngularJSのコアモジュールではなく別に用意されています。そのため、実際に使用する際には、リスト1のように別途読み込む必要があります。
<!DOCTYPE html>
<html lang="ja" ng-app="main" ng-controller="AppController">
<head>
<meta charset="UTF-8">
<!--(省略)-->
<script type="text/javascript" src="vendors/angular.js"></script>
<script type="text/javascript" src="vendors/angular-route.js"></script> <!-- (1) ngRouteモジュールを読み込む -->
<!--(省略)-->
</head>
<body>
<!--(省略)-->
<div class="main" ng-view></div> <!-- (2) テンプレートを差し込む要素の指定 -->
<!--(省略)-->
</body>
</html>
(1)ではngRouteモジュールを読み込みます。続いて、(2)ではテンプレートを読み込む場所を指定します。この場所に実際のコントローラとHTMLテンプレートによる処理結果が差し込まれます。また、AngularJSはコードを読み込んだだけでは使えませんので、リスト2のように依存モジュールとしてngRouteを指定することも忘れないようにしてください。
angular.module("main",["ngRoute"]);
ルーティングの指定
サンプルのアプリケーションはパス、コントーラ、HTMLテンプレートの関係が図3のようになります。
このルーティング指定を行ったものが、リスト3です。
var routes = angular.module("main.routes",["ngRoute"]) // (1) 別のモジュールとして指定
.config(function($routeProvider, $locationProvider){
//$locationProvider.html5Mode(true); // (2) HTML5モードとして動作させる場合
$routeProvider.when('/list',{ // (3) whenを使った指定
templateUrl : 'views/list.html',
controller : 'ListController'
}).when('/add',{
templateUrl : 'views/add.html',
controller : 'AddController',
resolve : { // (4) resolveを使った事前処理の実行
defaults : function(){
return {
date : new Date()
}
}
},
reloadOnSearch: false
}).when('/item/:uid',{
templateUrl : 'views/item.html',
controller : 'ItemController'
}).otherwise({ // (5) 指定パス以外の場合
redirectTo: '/list'
});
});
今回は(1)のようにルーティングに関する部分を別モジュールとして作成しています。続いてHTML5モードとして動作させる場合には$locationProviderサービスのhtml5Modeメソッドで(2)のように指定します。今回はhashモードとして動作させるためにコメントアウトされています。
hashモードとHTML5モードは以前にも紹介していますのでそちらを参照してください。また、パスとコントローラ、HTMLテンプレートを関連させるためには、(3)のように$routeProviderサービスのwhenメソッドを使います。また、指定以外のパスの場合には(5)のようにotherwiseメソッドを利用しますが、whenメソッドとotherwiseメソッドでは、表1に示すプロパティが指定できます。
| パラメータ名 | 説明 |
|---|---|
| controller | ルートにより表示されるテンプレートで利用するコントローラ |
| controllerAs | コントローラのエイリアス(テンプレート内でコントローラの指定の際に利用するasと同様) |
| template | 利用するテンプレートの文字列、もしくはテンプレートの文字列を返す関数を指定 |
| templateUrl | 利用するテンプレートのURLもしくは、そのURLを返す関数 |
| resolve | テンプレート処理が行われる前にコントローラへの依存データ、もしくは処理の追加 |
| redirectTo | リダイレクトパスの指定 |
| reloadOnSearch | true(デフォルト)もしくはfalseの指定。$location.searchもしくはpathが変わった時にルート先をリロードする。 |
| caseInsensitiveMatch | trueもしくはfalse(デフォルト)。trueの場合には、パスの大文字、小文字を区別しないようになる。 |
(4)はresolveプロパティを使った時のサンプルです。この例では追加画面のデフォルトの値を、resolveプロパティを使って指定しています。resolveプロパティの値はリスト4のようにコントローラを定義する際に依存指定で取得することができます。
module.controller('AddController',['$scope','$location','Items','defaults', // 同じ変数名を指定 - 'defaults'
function($scope,$location,Items,defaults){
$scope.item = angular.merge(defaults,{});
// 省略
}]);
このようにあるコントローラ特有の処理をサービスとして定義したものと同様に使えます。ただし、比較大きな処理になってしまう場合にはサービスとして定義したほうが良い場合もあり、開発者の好みにもよりますが、筆者の場合にはサンプルのようにコントローラのデフォルト値などはresolveプロパティで指定して可読性を統一するようにしています。
