rattkin
rattkin

Reputation: 647

Angular UI Router preventDefault causing erratic behaviour

app.run(['$rootScope', '$state', function($rootScope, $state) {
    $rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams){
        event.preventDefault();
        $state.go('error', null, { location: true, inherit: true, relative: $state.$current, notify: false });
    });
}]);

This doesn't seem to be working properly. Obviously it would trigger on any state (it's fine, it's just for testing), it doesn't allow for transition for the desired state (that's good), but it doesn't fully go to the new state I want it to go to. I have the 'error' bound properly in stateProvider

$stateProvider
        .state('error', {
            url: '/access-denied',
            templateUrl: 'application/view/error/error.html'
        });

What I can observe is that the url changes to /access-denied, and yet, the associated template doesn't render. The state works fine on it's own (when disabling the $stateChangeStart handler, if I use it's url, it renders properly).

It would look to me like it's a bug in UI router or maybe I'm missing something? It's the exact way of doing things as they have in their documentation FAQ.

HALP!

Upvotes: 3

Views: 2798

Answers (2)

ncuillery
ncuillery

Reputation: 15719

$stateChange...Whatever events are custom events triggered by the UI-router. Custom events have a preventDefault() only for similarity with DOM event. There is no action expect if someone use the defaultPrevented event attribute. https://github.com/angular/angular.js/blob/master/src/ng/rootScope.js#L1131

If you want to have an ineffective link, you must have to use ng-click directive and use preventDefault() in it (it will work because it will be a standard DOM event).

Upvotes: 0

homerjam
homerjam

Reputation: 679

I just came across this problem myself, after looking through the source it appears that the actual view transition/transclusion is triggered by the $stateChangeSuccess internally so therefore is also prevented by notify: false - this is somewhat counter intuitive, I've created an issue here.

As a work around you can trigger the event manually with the success callback of the promise returned by $state.go(). I've amended your example to show this below:

app.run(['$rootScope', '$state', function($rootScope, $state) {

    $rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams){
        event.preventDefault();

        $state.go('error', null, {notify: false}).then(function(state) {
            $rootScope.$broadcast('$stateChangeSuccess', state, null);
        });
    });

}]);

Upvotes: 4

Related Questions