Skip to content

no state change when navigating to a URL where only parameters change #289

@metamatt

Description

@metamatt

I'm trying to use ui-router and ran into a problem where if I attempt a transition between a state with params and the same state with different params, nothing happens.

In my use so far, I'm replacing existing use of ngRoute with ui-router components, so all the states have (distinct) URLs, and I'm using <a href> to transition between states.

Say I have a state users, defined something like state('users', { url: '/users', /* controller, template, etc */ }) and a state users.view, defined something like state('users.view', { url: '/:username', ... }). If we navigate from / to /users/foo, we see a state transition into users.view with params including { username: 'foo' }. If we then navigate to /users/bar, there's no further state transition.

In fact, I see urlRouterProvider's internal update() routine run and match the route and invoke the when handler added by $StateProvider.registerState(). But that handler's ($state.$current.navigable != state) test decides there's nothing to do. So no state transition happens, and as far as I can tell nothing else happens.

(I saw #46, but this seems to be different. And I tried putting a watch on $state.params from the controller, but the watch doesn't fire.)

If I comment out that test at line 119 of state.js, so that it always invokes $state.transitionTo, it works more like I'd expect.

Here's a minimal repro case:

<html>
<head>
<script src='./angular.js'></script>
<script src='./angular-ui-router.js'></script>
<script>

var testApp = angular.module('testApp', [ 'ui.state' ])
   .config(function($locationProvider, $stateProvider) {
      //$locationProvider.html5Mode(true);      
      $stateProvider
         .state('child', {
            template: '<p>Child state with param = "{{ param }}"</p>',
            url: '/:param',
            controller: childController
         });
   })
   .run(function($rootScope) {
      $rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams) {
         console.log('$stateChangeStart:', arguments);
      });
      $rootScope.$on('$stateChangeSuccess', function(event, toState, toParams, fromState, fromParams) {
         console.log('$stateChangeSuccess:', arguments);
      });
   });

function childController($scope, $state) {
   console.log('invoke childController with $state', $state);
   $scope.param = $state.params.param;

   $scope.$watch('$state.params.param', function() {
      console.log('childController watch param change to', $state.params.param);
   });
}

</script>
</head>

<body ng-app='testApp'>

<p>Choose param for child state:
   <a href='#/good'>good</a>
   <a href='#/bad'>bad</a>
   <a href='#/ugly'>ugly</a>
</p>

<ui-view>

</body>
</html>

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions