question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

ui-router keeps firing the `$stateChangeStart` when I try to go to an invalid AngularJS path and then block it.

See original GitHub issue

Thanks for your hard work on the ui-router code base.

If I navigate to an invalid AngularJS path and then block the state transition with event.preventDefault() inside a $stateChangeStart callback, I get:

Error: [$rootScope:infdig] 10 $digest() iterations reached. Aborting!
Watchers fired in the last 5 iterations: [["fn: $locationWatch; newVal: 7; oldVal: 6"],["fn: $locationWatch; newVal: 8; oldVal: 7"],["fn: $locationWatch; newVal: 9; oldVal: 8"],["fn: $locationWatch; newVal: 10; oldVal: 9"],["fn: $locationWatch; newVal: 11; oldVal: 10"]]

Here is my SSCCE:

<!doctype html>
  <head>
    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.js"></script>
    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular.js"></script>
    <script src="//cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.10/angular-ui-router.min.js"></script>
  </head>
  <body ng-app="clientApp">
    <div ui-view="" ></div>

    <script>
      var app = angular.module('clientApp', ['ui.router'])

      var myRouteProvider = [
                '$stateProvider', '$urlRouterProvider',
        function($stateProvider,   $urlRouterProvider) { 
          $urlRouterProvider.otherwise('/foo');
          $stateProvider.state('/foo', {
            url: '/foo',
            template: '<div>In Foo now</div>',
            reloadOnSearch: false
          })
        }]
      app.config(myRouteProvider)

      var authenticated = false
      app.run([
                 '$rootScope', '$log','$state','$timeout',
        function ($rootScope,   $log,  $state,  $timeout) {
          $rootScope.$on('$stateChangeStart', function (event, next, toParams) {
            if (!authenticated) {
              event.preventDefault()
              //following $timeout is emulating a backend $http.get('/auth/') request
              $timeout(function() {
                authenticated = true
                $state.go(next,toParams)
              },1000)
            }
          })
        }
      ])
    </script>
  </body>
</html>

Serve it up with python -m SimpleHTTPServer 7070 and go to localhost:7070/test.html#/bar to see it explode in your face. Whereas directly navigating to the only valid angularjs location does not blow up localhost:7070/test.html#/foo

Issue Analytics

  • State:closed
  • Created 9 years ago
  • Comments:8

github_iconTop GitHub Comments

1reaction
RossRogerscommented, Jul 31, 2014

Fakeout. This is an interaction issue between $urlRouterProvider and $stateProvider. I shouldn’t be using $urlRouterProvider for my otherwise. I should be using something like:

$stateProvider.state("otherwise", {
    url: "*path",
    template: "Invalid Location",
    controller: [
              '$timeout','$state',
      function($timeout,  $state ) {
        $timeout(function() {
          $state.go('/foo')
        },2000)
      }]
});

Or even a transparent’ish redirect:

$stateProvider.state("otherwise", {
    url: "*path",
    template: "",
    controller: [
              '$state',
      function($state) {
        $state.go('/foo')
      }]
});

Altogether now:

<!doctype html>
  <head>
    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.js"></script>
    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular.js"></script>
    <script src="//cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.10/angular-ui-router.min.js"></script>
  </head>
  <body ng-app="clientApp">
    <div ui-view="" ></div>

    <script>
      var app = angular.module('clientApp', ['ui.router'])

      var myRouteProvider = [
                '$stateProvider',
        function($stateProvider) { 

          $stateProvider.state('/foo', {
            url: '/foo',
            template: '<div>In Foo now</div>',
            reloadOnSearch: false
          })

          $stateProvider.state("otherwise", {
              url: "*path",
              template: "",
              controller: [
                        '$state',
                function($state) {
                  $state.go('/foo')
                }]
          });
        }]
      app.config(myRouteProvider)

      var authenticated = false
      app.run([
                 '$rootScope', '$log','$state','$timeout',
        function ($rootScope,   $log,  $state,  $timeout) {
          $rootScope.$on('$stateChangeStart', function (event, next, toParams) {
            if (!authenticated) {
              event.preventDefault()
              //following $timeout is emulating a backend $http.get('/auth/') request
              $timeout(function() {
                authenticated = true
                $state.go(next,toParams)
              },1000)
            }
          })
        }
      ])
    </script>
  </body>
</html>
0reactions
alexfernandez803commented, Oct 10, 2015

This one works for me, I got rid of the event.preventDefault() and made sure that there is a state to be executed.

  // Authorization Checking
  $rootScope.$on('$stateChangeStart', function (event, next) {
    if (Authentication.isAuthenticated()) {
      $state.go('app.dashboard-v1');
    } else {
      $state.go('access.signin1');
    }

  });
Read more comments on GitHub >

github_iconTop Results From Across the Web

Why does AngularJS with ui-router keep firing the ...
Looks like this is a bug with ui-router when you use the combination of $urlRouterProvider.otherwise("/foo) with the $stateChangeStart.
Read more >
Ng1_state_events - UI-Router
You can use event.preventDefault() to prevent the transition from happening and then the transition promise will be rejected with a 'transition prevented' value ......
Read more >
AngularJS UI-Router: Quick Start - Plunker
Do not include this module as a dependency * in your angular app (use {@link ... a path parameter matches any * number...
Read more >
AngularJS User Authentication Inside Your Ionic App - Devdactic
js and insert this: angular.module('starter') .constant('AUTH_EVENTS', { notAuthenticated: 'auth-not-authenticated', notAuthorized: ...
Read more >
ng-book (the complete book on angularjs) - StudyLib
A block of code looks like so: var App = angular.module('App', ... If you are using Windows, you can find your terminal by...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found