Подтвердить что ты не робот

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>
4b9b3361

Ответ 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.