AngularJS でテンプレートを入れ子にしたかったけど、ng-view は入れ子にできない。
つまり AngularJS の機能だけでは困難。
おまけに ng-view は複数置いて、別々のテンプレートを表示することもできないときた。
そんな ng-view や ngRoute に置き換わるのを目指したモジュールで、angular-ui-router がある。
こいつを使えばできそう。論よりコード。
<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>
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" }
];
}]);
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" }
];
}]);
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 本体に組み込む、なんて動きもあるみたいだけど、
早く進めて欲しいところだ。