angular-ui / ui-router

The de-facto solution to flexible routing with nested views in AngularJS
http://ui-router.github.io/
MIT License
13.54k stars 3k forks source link

location is not updated when url is an empty string #3563

Closed lafeuil closed 6 years ago

lafeuil commented 6 years ago

When I configure a state with this params :

state = {
  name: 'main',
  url: '/{id}',
  params: {
    id: {
      squash: true,
      value: null
    }
  },
}

and I go to this state with $state.go('main'), the location address bar is not updated. I take a look at code and I find that the new path is correctly generated by the urlMatcher and it returns an empty string. So, the new url in location address bar must be for example http://localhost. But the location service doesn't update the location when url is an empty string. The condition stops updating :

if (newUrl) this.$location.url(newUrl);

https://github.com/angular-ui/ui-router/blob/5b54cbf89db3a908fae55485d2796ce79f4dea2e/src/locationServices.ts#L49

lafeuil commented 6 years ago

I have found a workaround to reinitialize the url in location address bar.

I define the onEnter and onRetain hooks in the state to fix the url to an empty string when the param id is not defined :

// FIX https://github.com/angular-ui/ui-router/issues/3563
onEnter: ['$location', '$transition$', function($location, $transition$) {
    var targetState = $transition$.targetState()
    if (targetState.name() === 'main.show' && !targetState.params().id) $location.url('')
}],
onRetain: ['$location', '$transition$', function($location, $transition$) {
    var targetState = $transition$.targetState()
    if (targetState.name() === 'main.show' && !targetState.params().id) $location.url('')
}]
christopherthielen commented 6 years ago

http://plnkr.co/edit/TzIIUjuWvhXb5fHwJxRX?p=preview

aj-dev commented 6 years ago

I have experienced a weird side effect caused by this bug fix. All state config tests started failing and the reason was that I had 'url': '' in state configs

$stateProvider.state('anon.landing', {
            url: '',
            abstract: true,
            views: {
               ...
                }
            }
        });

so this.$location.url() in https://github.com/angular-ui/ui-router/blob/1.0.16/src/locationServices.ts#L71 was being invoked with an empty string. Removing 'url': '' option from state config solved it. Then newUrl is undefined and if (isDefined(newUrl)) this.$location.url(newUrl); does not update location url.