-
Notifications
You must be signed in to change notification settings - Fork 3k
Description
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>