Angular-ui-router获得之前的状态

有没有办法获得当前状态的前一个状态?

例如,我想知道之前的状态是在当前状态B之前(之前的状态将是状态A)。

我无法在ui-router github文档页面中find它。

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; }] } }); }]); 

为了便于阅读,我将把我的解决scheme(基于stu.salsbury的anwser)放在这里。

将此代码添加到您的应用程序的抽象模板,以便在每个页面上运行。

 $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中的更改。 它非常方便。

在下面的示例中,我创build了一个decorator (在configuration阶段,每个应用只运行一次),并向$state服务添加了一个额外的属性,所以这种方法不会将全局variables添加到$rootscope ,也不需要添加任何额外的依赖项服务比$state

在我的示例中,我需要将用户redirect到索引页面,当他已经login,并且在login后不要将其redirect到以前的“受保护”页面时。

唯一未知的服务(为你),我使用的是authenticationFactoryappSettings

  • authenticationFactory只是pipe理用户login。 在这种情况下,我只使用一种方法来确定用户是否login。
  • appSettings是常量,不用在任何地方使用string。 appSettings.states.loginappSettings.states.register包含login和注册url的状态的名称。

然后在任何controller / service等您需要注入$state服务,您可以访问当前和以前的URL像这样:

  • 当前: $state.current.name
  • Previous: $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.17angularjs 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上添加一个名为{previous}的新属性到$ state

 $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 ); 

我对Endy Tjahjono用的是类似的方法。

我所做的是在转换之前保存当前状态的值。 让我们看一个例子。 想象一下,在执行任何触发转换时执行的函数:

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

这里的关键是params对象(将被发送到状态的参数映射) – > { previousState : { name : $state.current.name } }

注意:请注意,我只是“保存”$ state对象的名称属性,因为是我唯一需要保存状态的东西。 但是我们可以拥有整个国家对象。

然后,状态“无论”定义如下:

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

这里的关键点是params对象。

 params : { previousState: null, } 

那么,在这个状态下,我们可以得到如下的状态:

 $state.params.previousState.name 

这里是Chris Thielen ui-router-extras:$ previousState的一个非常优雅的解决scheme

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

previous是一个对象,看起来像: { state: fromState, params: fromParams }其中fromState是之前的状态,fromParams是之前的状态参数。

我坚持相同的问题,并find最简单的方法来做到这一点…

 //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(); }; 

(如果你希望它更可testing,注入$窗口服务到你的控制器,并使用$ window.history.back())。

如果你只是需要这个function,并希望在多个控制器中使用它,这是一个简单的服务来跟踪路线的历史logging:

  (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; } })(); 

其中.module('core')中的'core'将是你的应用程序/模块的名称。 需要服务作为依赖到你的控制器,然后在你的控制器,你可以这样做: $scope.routeHistory = RouterTracker.getRouteHistory()

好的,我知道我在这里参加派对的时间已经晚了,但是我对这个angular色很陌生。 我正在试图使这适合在这里的约翰爸爸风格指南 。 我想使这个可重用,所以我创build了一个块。 这是我想出来的:

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; }); } } })(); 

core.module

 (function () { 'use strict'; angular.module('myApp.Core', [ // Angular modules 'ngMessages', 'ngResource', // Custom modules 'blocks.previousState', 'blocks.router' // 3rd Party Modules ]); })(); 

core.config

 (function () { 'use strict'; var core = angular.module('myApp.Core'); core.run(appRun); function appRun(previousState) { // do nothing. just instantiating the state handler } })(); 

任何批评这个代码只会帮助我,所以请让我知道我可以改善这个代码。

一个非常简单的解决scheme就是编辑$ state.current.namestring,并在最后的'。 – 你得到父母国家的名字。 如果您在状态之间跳转很多,则这不起作用,因为它只是parsing当前path。 但是,如果你的状态与你实际所在的地方相符,那么这个工作就行。

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

你可以这样返回状态:

 $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); }; }; })();