Why does this Angular ui router code cause an infinite loop in $digest?

风流意气都作罢 提交于 2019-12-12 10:58:25

问题


I've boiled the code down as much as I can. Something about nested states and the event handling/broadcasting is causing an infinite loop. In Chrome I can pause it and see that it is looping forever in Angular's $digest function. Any idea why? Is it a bug in my example code, or a bug in Angular, or the UI Router?

<!doctype html>
<html ng-app='bugapp' ng-controller='BugAppCtrl'>
<head>
  <script src='//code.jquery.com/jquery-1.10.1.min.js'></script>

  <!-- Angular 1.2.11 -->
  <script src='//ajax.googleapis.com/ajax/libs/angularjs/1.2.11/angular.js'></script>

  <!-- UI router 0.2.8 -->
  <script src='//cdn.jsdelivr.net/angular.ui-router/0.2.8/angular-ui-router.js'></script>

  <script>
angular.module('bugapp', ['ui.router'])
  .run(function ($rootScope, $state, $stateParams) {
    $rootScope.$state = $state;
    $rootScope.$stateParams = $stateParams;
  })
  .config(function ($locationProvider, $stateProvider, $urlRouterProvider) {
    $locationProvider.html5Mode(false);

    $stateProvider
      .state("root", {
        abstract: true,
        url: "/servletContext?asUser",
        template: '<div ui-view></div>'  // ???
      })
      .state("root.home", {
        abstract: true,
        url: "/home",
        template: "<div ng-if='hasData()' ui-view ></div>"

      })
      .state("root.home.profile", {
        url: "/profile",
        template: '<div>whatever</div>'
      })

  })
  .controller('BugAppCtrl', function ($scope, $state, $stateParams, $log, $location) {
    $log.log('BugAppCtrl: constructor');

    $scope.hasData = function() {
      var res = !!$scope.foo;
      // $log.log("hasData called, returing " + res + " foo is " + $scope.foo);
      return res;
    };

    $scope.$on('$stateChangeSuccess', function () {
      $log.log("State changed! (to " + $state.current.name + ")");
      $scope.foo = 'junk';
      $scope.$broadcast("resetfoo");
    });

    $state.go('root.home.profile');
  });
  </script>
</head>
<body>
  <div ui-view></div>
</body>
</html>

回答1:


I suspect this is a bug in the UI Router, for two reasons:

  1. I tried your code and then tried downgrading the version of UI Router to 0.2.7. When I used 0.2.7, it worked.
  2. Even if you keep using version 0.2.8 of UI Router, if you perform the state change through $location instead of $state, it works. Here's an example of using $location instead of the $state.go call:

    $location.path('/servletContext/home/profile');
    

Although I use and recommend UI Router (can't do without nested views), if you find in the future that you want to do any sort of intercepting or redirecting when the user tries to go to certain pages, I recommend using $location.path instead of $state, for reasons I described in a blog post

Edit: I haven't tried with parameters before but just tried with the code you posted (I created a 2nd controller and assigned it to your 'root.home.profile' state), and it works. Instructions from UI Router are here. But basically if you set your URL in your state definition the same way you would with UI Router:

url: "/profile/:foo",

then in your $location.path call add the parameter in the path:

$location.path('/servletContext/home/profile/12');

and you can access the 12 in the controller from

$stateParams.foo


来源:https://stackoverflow.com/questions/21631896/why-does-this-angular-ui-router-code-cause-an-infinite-loop-in-digest

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!