Angular UI-маршрутизатор Вложенное разрешение состояния в дочерних состояниях
В приложении angular, над которым я работаю, я хотел бы, чтобы там было абстрактное родительское состояние, которое должно разрешать определенные зависимости для всех его дочерних состояний. В частности, я хотел бы, чтобы все состояния требовали, чтобы аутентифицированный пользователь наследовал эту зависимость от некоторого состояния authroot.
Я сталкиваюсь с проблемами, когда зависимость родителя не всегда решается. В идеале, я хотел бы, чтобы родительское состояние проверяло, что пользователь все равно регистрируется для любого дочернего состояния автоматически. В docs говорится:
Дочерние состояния наследуют разрешенные зависимости от родительского состояния (состояний), которые они могут перезаписать.
Я нахожу, что родительская зависимость решается только тогда, когда я ввожу какое-либо дочернее состояние из состояния вне родителя, но не при перемещении между состояниями сестры.
В этом примере, если вы перемещаетесь между состояниями authroot.testA и authroot.testB, метод GetUser вызывается только один раз. Когда вы перейдете в состояние other
и обратно, он снова запустится.
Я могу установить зависимость User от каждого из дочерних состояний, чтобы гарантировать, что метод вызывается каждый раз, когда вы вводите какое-либо из этих состояний, но это, похоже, преследует цель унаследованной зависимости.
Я неправильно понимаю документы? Есть ли способ заставить родительское состояние повторно разрешать свои зависимости, даже когда состояние изменяется между братьями и сестрами?
jsfiddle
<!doctype html>
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.2.1/angular.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.0/angular-ui-router.min.js"></script>
<script>
(function(ng) {
var app = ng.module("Test", ["ui.router"]);
app.config(["$stateProvider", "$urlRouterProvider", function(sp, urp) {
urp.otherwise("/testA");
sp.state("authroot", {
abstract: true,
url: "",
template: "<div ui-view></div>",
resolve: {User: ["UserService", function(UserService) {
console.log("Resolving dependency...");
return UserService.GetUser();
}]}
});
sp.state("authroot.testA", {
url: "/testA",
template: "<h1>Test A {{User|json}}</h1>",
controller: "TestCtrl"
});
sp.state("authroot.testB", {
url: "/testB",
template: "<h1>Test B {{User|json}}</h1>",
controller: "TestCtrl"
});
sp.state("other", {
url: "/other",
template: "<h1>Other</h1>",
});
}]);
app.controller("TestCtrl", ["$scope", "User", function($scope, User) {$scope.User = User;}]);
app.factory("UserService", ["$q", "$timeout", function($q, $timeout) {
function GetUser() {
console.log("Getting User information from server...");
var d = $q.defer();
$timeout(function(){
console.log("Got User info.");
d.resolve({UserName:"JohnDoe1", OtherData: "asdf"});
}, 500);
return d.promise;
};
return {
GetUser: GetUser
};
}]);
})(window.angular);
</script>
</head>
<body ng-app="Test">
<a ui-sref="authroot.testA">Goto A</a>
<a ui-sref="authroot.testB">Goto B</a>
<a ui-sref="other">Goto Other</a>
<div ui-view>Loading...</div>
</body>
</html>
Ответы
Ответ 1
То, как я обнаружил, что ui-router исключительный, находится в поведении, которое вы только что описали.
Подумайте о какой-либо сущности, например. Контакт. Поэтому было бы неплохо иметь правую сторону, показывающую нам список контактов, левую часть детали. Пожалуйста, ознакомьтесь с Основы использования ui-router с AngularJS для быстрого преодоления макета. Цитата:
ui-router полностью охватывает государственную машину системы маршрутизации. Это позволяет вам определять состояния и переводить ваше приложение на эти государства. Реальная победа заключается в том, что она позволяет отделить вложенные состояний и делает некоторые очень сложные макеты элегантным способом.
Вам нужно подумать о своей маршрутизации немного по-другому, но как только вы оглянитесь вокруг государственного подхода, я думаю, вам понравится он.
Хорошо, зачем это все?
Потому что мы можем иметь состояние Contact
, представляющее список. Произнесите фиксированный список из перспективы детали. (Пропустить фильтрацию подкачки в настоящий момент). Мы можем щелкнуть по списку и перейти в состояние Contact.Detail(ID)
, чтобы увидеть только выбранный элемент. Затем выберите другой контакт/элемент.
Здесь преимущество вложенных состояний:
Список (состояние Contact
) перезагружается не. Пока дочернее состояние Contact.Detail
есть.
Это должно объяснить, почему "странное" поведение следует рассматривать как правильное.
Чтобы ответить на ваш вопрос, как обращаться с состоянием пользователя. Я бы использовал несколько самых близких родственников состояния маршрута, с его разделенным представлением и контроллером и некоторым жизненным циклом arround... срабатывающим в некоторых циклах
Ответ 2
Настоящий короткий ответ используется:
$rootScope.$on("$stateChangeStart")
для прослушивания любых изменений области и выполнения соответствующих действий.
Дольше ответ, посмотрите скрипку:
http://jsfiddle.net/jasallen/SZGjN/1/
Обратите внимание, что я использовал app.run, что означает, что я разрешаю пользователю для каждого изменения состояния. Если вы хотите ограничить его изменениями состояния, в то время как authRoot находится в родительском состоянии, поместите проверку для $stateChangeStart
в контроллер authRoot.