AngularJS でテンプレートを入れ子にしたかったけど、ng-view は入れ子にできない。 つまり AngularJS の機能だけでは困難。 おまけに ng-view は複数置いて、別々のテンプレートを表示することもできないときた。
そんな ng-view や ngRoute に置き換わるのを目指したモジュールで、angular-ui-router がある。
こいつを使えばできそう。論よりコード。
<!DOCTYPE html> <html ng-app="UIRouterSample"> <head> <meta charset="utf-8"> <title>UIRouterSample</title> </head> <body ng-controller="MainCtrl"> <ul> <li ng-repeat="label in labels"> <a ui-sref="label({ labelName: label.name })" ng-bind="label.name"></a> </li> </ul> <div ui-view></div> <script id="mails_template" type="text/ng-template"> <table class="table"> <thead> <tr> <th>Title</th> </tr> </thead> <tbody> <tr ng-repeat="mail in mails"> <td><a ui-sref=".thread({mailId:mail.id})" ng-bind="mail.title"></a></td> </tr> </tbody> </table> <div ui-view></div> </script> <script id="thread_template" type="text/ng-template"> <table class="table"> <thead> <tr> <th>Title</th> <th>Message</th> </tr> </thead> <tbody> <tr ng-repeat="mail in mails"> <td ng-bind="mail.title"></td> <td ng-bind="mail.message"></td> </tr> </tbody> </table> </script> <script src="angular.js"></script> <script src="angular-ui-router.js"></script> <script> // ui.router を使う window.App = angular.module("UIRouterSample", ["ui.router"]); App.controller("MainCtrl", ["$scope", function($scope) { $scope.labels = [ { id: 1, name: "today" }, { id: 2, name: "someday" }, { id: 3, name: "scheduled" } ]; }]); // $stateParams からパラメータを取り出せる App.controller("MailsCtrl", ["$scope", "$stateParams", function($scope, $stateParams) { var prefix = $stateParams.labelName + "_"; $scope.mails = [ { id: 1, title: prefix + "aaaaaa" }, { id: 2, title: prefix + "bbbbbb" }, { id: 3, title: prefix + "cccccc" } ]; }]); App.controller("ThreadCtrl", ["$scope", "$stateParams", function($scope, $stateParams) { var prefix = "mail" + $stateParams.mailId + "_"; $scope.mails = [ { id: 1, title: "aaaaaa", message: prefix + "hogehoge" }, { id: 2, title: "bbbbbb", message: prefix + "fugafuga" }, { id: 3, title: "cccccc", message: prefix + "foobar" } ]; }]); // ステートを登録 // URL・コントローラー・テンプレートのセットに名前を付ける App.config(["$stateProvider", "$urlRouterProvider", function($stateProvider, $urlRouterProvider) { $stateProvider. state("label", { url: "/labels/{labelName:[a-zA-Z]+}", controller: "MailsCtrl", templateUrl: "mails_template" }). state("label.thread", { url: "/thread/{mailId:[0-9]+}", controller: "ThreadCtrl", templateUrl: "thread_template" }); }]); </script> </body> </html>
URL とコントローラーとテンプレートをセットにして「ステート」として扱っている。 ステートというより、Django のエンドポイントに近い気がする。 名前から URL を逆引きできるし。
angular-ui-router を AngularJS 本体に組み込む、なんて動きもあるみたいだけど、 早く進めて欲しいところだ。