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プロパティで指定して可読性を統一するようにしています。