Angular-ui-router получить предыдущее состояние



есть ли способ получить предыдущее состояние текущего состояния?



например, я хотел бы знать, что предыдущее состояние было до текущего состояния B (где предыдущее состояние было бы состоянием A).



Я не могу найти его на страницах ui-router GitHub doc.

656   13  

13 ответов:

ui-router не отслеживает предыдущее состояние после его перехода, но событие $stateChangeSuccess транслируется на $rootScope при изменении состояния.

вы должны быть в состоянии поймать предыдущее состояние от этого события (from это состояние, которое вы покидаете):

$rootScope.$on('$stateChangeSuccess', function (ev, to, toParams, from, fromParams) {
   //assign the "from" parameter to something
});

Я использую resolve для сохранения данных текущего состояния перед переходом в новое состояние:

angular.module('MyModule')
.config(['$stateProvider', function ($stateProvider) {
    $stateProvider
        .state('mystate', {
            templateUrl: 'mytemplate.html',
            controller: ["PreviousState", function (PreviousState) {
                if (PreviousState.Name == "mystate") {
                    // ...
                }
            }],
            resolve: {
                PreviousState: ["$state", function ($state) {
                    var currentStateData = {
                        Name: $state.current.name,
                        Params: $state.params,
                        URL: $state.href($state.current.name, $state.params)
                    };
                    return currentStateData;
                }]
            }
        });
}]);

для удобства чтения я размещу свое решение (на основе stu.ответить на Сэлсбери-х) здесь.

добавьте этот код в абстрактный шаблон вашего приложения, чтобы он работал на каждой странице.

$rootScope.previousState;
$rootScope.currentState;
$rootScope.$on('$stateChangeSuccess', function(ev, to, toParams, from, fromParams) {
    $rootScope.previousState = from.name;
    $rootScope.currentState = to.name;
    console.log('Previous state:'+$rootScope.previousState)
    console.log('Current state:'+$rootScope.currentState)
});

отслеживает изменения в rootScope. Это довольно удобно.

в следующем примере я создал decorator (выполняется только один раз для каждого приложения на этапе настройки) и добавляет дополнительное свойство к $state службы, так что этот подход не добавить глобальные переменные $rootscope и не требует добавления каких-либо дополнительных зависимостей к другим службам, чем $state.

в моем примере мне нужно было перенаправить пользователя на страницу индекса, когда он уже вошел в систему, и когда он не должен был перенаправлять его на предыдущую "защищенную" страницу после регистрироваться.

единственные неизвестные услуги (для вас), которые я использую authenticationFactory и appSettings:

  • authenticationFactory просто пишет имя пользователя. В этом случае я использую только метод, чтобы определить, если пользователь вошел в систему или нет.
  • appSettings являются константами только для того, чтобы не использовать строки везде. appSettings.states.login и appSettings.states.register содержит имя состояния для входа и регистрации url.

потом в любом controller/service и т. д. Вам нужно впрысните $state сервис и вы можете получить доступ к текущему и предыдущему url-адресу следующим образом:

  • Current:$state.current.name
  • Предыдущее значение: $state.previous.route.name

из консоли Chrome:

var injector = angular.element(document.body).injector();
var $state = injector.get("$state");
$state.current.name;
$state.previous.route.name;

реализация:

(я использую angular-ui-router v0.2.17 и angularjs v1.4.9)

(function(angular) {
    "use strict";

    function $stateDecorator($delegate, $injector, $rootScope, appSettings) {
        function decorated$State() {
            var $state = $delegate;
            $state.previous = undefined;
            $rootScope.$on("$stateChangeSuccess", function (ev, to, toParams, from, fromParams) {
                $state.previous = { route: from, routeParams: fromParams }
            });

            $rootScope.$on("$stateChangeStart", function (event, toState/*, toParams, fromState, fromParams*/) {
                var authenticationFactory = $injector.get("authenticationFactory");
                if ((toState.name === appSettings.states.login || toState.name === appSettings.states.register) && authenticationFactory.isUserLoggedIn()) {
                    event.preventDefault();
                    $state.go(appSettings.states.index);
                }
            });

            return $state;
        }

        return decorated$State();
    }

    $stateDecorator.$inject = ["$delegate", "$injector", "$rootScope", "appSettings"];

    angular
        .module("app.core")
        .decorator("$state", $stateDecorator);
})(angular);

добавить новое свойство, которое называется {предыдущий} до $состояние на $stateChangeStart

$rootScope.$on( '$stateChangeStart', ( event, to, toParams, from, fromParams ) => {
    // Add {fromParams} to {from}
    from.params = fromParams;

    // Assign {from} to {previous} in $state
    $state.previous = from;
    ...
}

Теперь в любом месте вы можете использовать $state у вас будет предыдущий доступный

previous:Object
    name:"route name"
    params:Object
        someParam:"someValue"
    resolve:Object
    template:"route template"
    url:"/route path/:someParam"

и использовать его вот так:

$state.go( $state.previous.name, $state.previous.params );

я использую подобный подход к тому, что Энди Tjahjono делает.

то, что я делаю, это сохранить значение текущего состояния перед переходом. Давайте посмотрим на примере; представьте это внутри функции, выполняемой при клике на то, что вызывает переход:

$state.go( 'state-whatever', { previousState : { name : $state.current.name } }, {} );

ключом здесь является объект params (карта параметров, которые будут отправлены в состояние) ->{ previousState : { name : $state.current.name } }

Примечание: обратите внимание, что Im только "сохранение" атрибут name объекта $state, потому что это единственное, что мне нужно для спасения государства. Но мы могли бы иметь весь государственный объект.

затем состояние "что угодно" было определено следующим образом:

.state( 'user-edit', {
  url : 'whatever'
  templateUrl : 'whatever',
  controller: 'whateverController as whateverController',
  params : {
    previousState: null,
  }
});

здесь ключевым моментом является объект params.

params : {
  previousState: null,
}

затем, внутри этого состояния, мы можем получить предыдущее состояние следующим образом:

$state.params.previousState.name

Я застрял с той же проблемой и найти самый простой способ сделать это...

//Html
<button type="button" onclick="history.back()">Back</button>

или

//Html
<button type="button" ng-click="goBack()">Back</button>

//JS
$scope.goBack = function() {
  window.history.back();
};

(Если вы хотите, чтобы он был более тестируемым, введите службу $window в свой контроллер и используйте $window.история.спина.))(

вот действительно элегантное решение от Криса Тилена ui-router-дополнительно: $previousState

var previous = $previousState.get(); //Gets a reference to the previous state.

previous - это объект, который выглядит так: { state: fromState, params: fromParams } где fromState-предыдущее состояние, а fromParams - предыдущие параметры состояния.

хорошо, я знаю, что я опаздываю на вечеринку здесь, но я новичок в angular. Я пытаюсь сделать это вписаться в John Papa style guide здесь. Я хотел сделать это многоразовым, поэтому я создал в блоке. Вот что я придумал:

previousStateProvider

(function () {
'use strict';

angular.module('blocks.previousState')
       .provider('previousState', previousStateProvider);

previousStateProvider.$inject = ['$rootScopeProvider'];

function previousStateProvider($rootScopeProvider) {
    this.$get = PreviousState;

    PreviousState.$inject = ['$rootScope'];

    /* @ngInject */
    function PreviousState($rootScope) {
        $rootScope.previousParms;
        $rootScope.previousState;
        $rootScope.currentState;

        $rootScope.$on('$stateChangeSuccess', function (ev, to, toParams, from, fromParams) {
            $rootScope.previousParms = fromParams;
            $rootScope.previousState = from.name;
            $rootScope.currentState = to.name;
        });
    }
}
})();

ядра.модуль

(function () {
'use strict';

angular.module('myApp.Core', [
    // Angular modules 
    'ngMessages',
    'ngResource',

    // Custom modules 
    'blocks.previousState',
    'blocks.router'

    // 3rd Party Modules
]);
})();

ядра.конфигурации

(function () {
'use strict';

var core = angular.module('myApp.Core');

core.run(appRun);

function appRun(previousState) {
    // do nothing. just instantiating the state handler
}
})();

любая критика по этому коду только поможет мне, поэтому, пожалуйста, позвольте я знаю, где я могу улучшить этот код.

Если вам просто нужна эта функциональность и вы хотите использовать ее в нескольких контроллерах, это простой сервис для отслеживания истории маршрутов:

  (function () {
  'use strict';

  angular
    .module('core')
    .factory('RouterTracker', RouterTracker);

  function RouterTracker($rootScope) {

    var routeHistory = [];
    var service = {
      getRouteHistory: getRouteHistory
    };

    $rootScope.$on('$stateChangeSuccess', function (ev, to, toParams, from, fromParams) {
      routeHistory.push({route: from, routeParams: fromParams});
    });

    function getRouteHistory() {
      return routeHistory;
    }

    return service;
  }
})();

где "ядра" в .модуль ("ядро") - это имя вашего приложения/модуля. Требуйте сервис как зависимость от вашего контроллера, тогда в вашем контроллере вы можете сделать:$scope.routeHistory = RouterTracker.getRouteHistory()

очень простое решение-просто отредактировать $state.current.name нанизать и вырезать все, в том числе и после последнего '.- вы получаете имя родительского государства. Это не работает, если вы много прыгаете между состояниями, потому что он просто анализирует текущий путь. Но если ваши состояния соответствуют тому, где вы на самом деле находитесь, то это работает.

var previousState = $state.current.name.substring(0, $state.current.name.lastIndexOf('.'))
$state.go(previousState)

я отслеживаю предыдущие состояния в $rootScope, поэтому всякий раз, когда это необходимо, я просто вызову нижеприведенную строку кода.

$state.go($rootScope.previousState);

на приложение.js:

$rootScope.$on('$stateChangeSuccess', function(event, to, toParams, from, fromParams) {
  $rootScope.previousState = from.name;
});

Вы можете вернуть состояние таким образом:

$state.go($state.$current.parent.self.name, $state.params);

пример:

(function() {
    'use strict'

    angular.module('app')
        .run(Run);

    /* @ngInject */
    function Run($rootScope, $state) {

        $rootScope.back = function() {
            $state.go($state.$current.parent.self.name, $state.params);
        };

    };

})();

Comments

    Ничего не найдено.