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到以前的“受保护”页面时。
唯一未知的服务(为你),我使用的是authenticationFactory
和appSettings
:
-
authenticationFactory
只是pipe理用户login。 在这种情况下,我只使用一种方法来确定用户是否login。 -
appSettings
是常量,不用在任何地方使用string。appSettings.states.login
和appSettings.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.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上添加一个名为{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); }; }; })();
- Angularjs $ state在新标签中打开链接
- Angular – UI路由器 – 以编程方式添加状态
- 如何使用ui-router为AngularJS提取查询参数?
- ionic framework$ state.go('app.home'); 在页面上添加我想要去(如何删除它)的返回button?
- 当我使用async / awaitfunction时,Angular UI路由器不处理parsing函数?
- 停止angularUI路由器导航,直到承诺解决
- Angular js – route-ui添加默认参数
- 当用户使用UI-Router转换到其父状态时,将用户引导到子状态
- 离子历史是如何工作的,何时创build非根堆栈?