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

问题描述 投票:145回答:14

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

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

我无法在ui-router github doc页面中找到它。

angularjs angular-ui-router angularjs-routing
14个回答
129
投票

ui-router一旦转换就不跟踪先前的状态,但是当状态改变时,事件$stateChangeSuccess$rootScope上广播。

您应该能够从该事件中捕获先前的状态(from是您要离开的州):

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

2
投票

如果您只需要此功能并希望在多个控制器中使用它,这是一个跟踪路径历史记录的简单服务:

  (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'将是你的app / module的名称。需要将服务作为对控制器的依赖,然后在控制器中执行:$scope.routeHistory = RouterTracker.getRouteHistory()


1
投票

我在$ rootScope中跟踪以前的状态,所以无论何时需要我都会调用下面的代码行。

$state.go($rootScope.previousState);

在App.js中:

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

0
投票

对于UI-Router(> = 1.0),不推荐使用StateChange事件。有关完整的迁移指南,请单击here

要获取UI-Router 1.0+中当前状态的先前状态:

app.run(function ($transitions) {
    $transitions.onSuccess({}, function (trans) {
         // previous state and paramaters
         var previousState = trans.from().name;
         var previousStateParameters = trans.params('from');
    });
});

-1
投票

一个非常简单的解决方案就是编辑$ state.current.name字符串并删除包括和在最后一个'。'之后的所有内容。 - 你得到父州的名字。如果你在状态之间跳转很多,这不起作用,因为它只是解析当前路径。但是如果你的状态与你实际所在的位置相对应,那么这就行了。

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

-2
投票

你可以这样返回状态:

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

    };

})();

142
投票

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

98
投票

为了便于阅读,我将在此处提供我的解决方案(基于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中的更改。它非常方便。


14
投票

在下面的示例中,我创建了一个decorator(在配置阶段每个应用程序只运行一次)并为$state服务添加了一个额外的属性,因此这种方法不会向$rootscope添加全局变量,也不需要向其他服务添加任何额外的依赖项。 $state

在我的示例中,我需要在用户登录时将用户重定向到索引页面,并且在登录后他不会将用户重定向到之前的“受保护”页面。

我使用的唯一未知服务(authenticationFactoryappSettings):

  • authenticationFactory只管理用户登录。在这种情况下,我只使用一种方法来识别用户是否登录。
  • appSettings是常量,只是因为不使用字符串。 appSettings.states.loginappSettings.states.register包含登录和注册URL的状态名称。

然后在任何controller / service等你需要注入$state服务,你可以访问当前和以前的网址,如下所示:

  • 目前:$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.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);

12
投票

在$ stateChangeStart上向$ state添加一个名为{previous}的新属性

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

9
投票

我遇到同样的问题,找到最简单的方法来做到这一点......

//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.history.back())。


8
投票

我使用类似于Endy Tjahjono的方法。

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

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

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

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

然后,声明“无论”定义如下:

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

这里,关键点是params对象。

params : {
  previousState: null,
}

然后,在该状态内,我们可以像这样得到之前的状态:

$state.params.previousState.name

6
投票

这是来自Chris Thielen ui-router-extras: $previousState的非常优雅的解决方案

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

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


4
投票

好吧,我知道我在这里参加派对已经迟到了,但我是新手。我想在这里使这适合John Papa style guide。我想让这个可重用,所以我创建了一个块。这是我想出的:

以前的StateProvider

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

对此代码的任何批评只会对我有所帮助,所以请告诉我在哪里可以改进此代码。

© www.soinside.com 2019 - 2024. All rights reserved.