$ on(' $ stateChangeStart')内的Ui-Router $ state.go正在引发无限循环

时间:2014-11-07 08:18:36

标签: angularjs angular-ui-router

我正在尝试将登录信息引入用户在应用程序中导航的方式。

如果该页面符合特定要求,我假装将用户重定向到他导航到登录页面之前的页面

防止来自$ stateChangeStart的事件停止状态改变如预期但当我运行$ state.go('into_somewhere')时我进入无限循环

我的角度版本是1.3.1,ui-router是最新的

.factory('RouteHistory', function ($rootScope,$log, $state, Auth, $urlRouter, $timeout) {

    // after the user enter a page
    var currentState = '';

    // when the user is trying to access a page that he has not permissions
    // or that requires the user to be logged in
    var pendingState = '';

    var isMenuTogglerVisible = false;
    var skipFromStateVal = true;

    $rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams){

      event.preventDefault();



      if (toState.name == 'login' && fromState.name != 'login'){
        $log.log('Ui-router: changing to login');
        // $urlRouter.sync();
        $state.go('login')
        //pendingState = fromState;
        //$log.log('Peding state updated to:' + pendingState.name );
        //$urlRouter.sync();
      }

      if (fromState.name == 'login' && Auth.isLoggedIn()) {
        $log.log('Ui-router: going from login');
        //$state.go(fromState.name);
        $timeout(function(){
          // $state.go('home', null, {/*reload: true, location: 'replace'*/});
          $state.go('browse-machine');
          //$urlRouter.sync();
        },2000)
      }



      $log.log({
        'toState': toState,
        'toParams': toParams,
        'fromState': fromState,
        'fromParams': fromParams
      })

    })


    return {

    };
  });

6 个答案:

答案 0 :(得分:12)

一般情况下,我会说,让我们只在需要时重定向$state.go() 。在其他情况下,从事件监听器中退出:

if (toState.name === 'login' ){
  // doe she/he try to go to login? - let him/her go
  return;
}

if(Auth.isLoggedIn()){
   // is logged in? - can go anyhwere
   return;
}

// else
$state.go('login')

这是简化的逻辑,但表明我们应该只在需要时改为执行。还有一些其他考试有更详细的实施和掠夺者:

根据评论中提供的内容plunker,我更改了here

...
// three new lines
if (toState.name === 'specialRoute'){
  return;
}

if (fromState.name=='route1'){
  event.preventDefault();
  $state.go('specialRoute')
}

这是循环了。请检查here

答案 1 :(得分:8)

您应该使用通知选项:

$state.go('your.state',{ your params },{notify: false});

这将阻止stateChangeStart再次触发。

答案 2 :(得分:6)

这个答案对我有所帮助:

$urlRouterProvider.otherwise( function($injector, $location) {
            var $state = $injector.get("$state");
            $state.go("app.home");
        });

原件: Why does AngularJS with ui-router keep firing the $stateChangeStart event?

答案 3 :(得分:1)

我只是使用$location.path('every/where')而不是$state.go('every/where')

:)。

答案 4 :(得分:1)

无限循环部分由

引起
if (toState.name == 'login' ...) { $state.go('login'); ...

..说if你要进入登录状态,then进入登录状态。

...调用event.preventDefault()作为事件处理程序中的第一行没有帮助。当您使用go()转到登录屏幕(或其他任何位置)时,event.preventDefault()阻止 阻止该状态更改。它只能在if内使用。

你的整个$ stateChangeStart处理程序应该是......

if (!Auth.isLoggedIn() && toState.name != 'login') {
    event.preventDefault();
    Auth.desiredState = toState.name;
    $state.go('login');
}

......自然而然地阅读。 “If你还没有登录,而你还没有进入登录界面,then停止你正在做的事情,我会记得你想去的地方,现在你走了到登录界面。“

稍后,当Auth对象对用户满意时,会发出$state.go(Auth.desiredState)

答案 5 :(得分:1)

它对我有用,下面的代码有助于摆脱无限循环

  let firstPass = true;
  $scope.$on('$stateChangeStart', function(event, toState, toParams) {
    if ($scope.addForm.$dirty && firstPass) {
      event.preventDefault();
      ConfirmationDialog.openNavigateAwayConfirmationModal().then(function () {
        firstPass = false;
        return $state.go(toState, toParams);
      });
      firstPass = true;
    }
  });