Why does $state.transitionTo or $state.go does not

2019-02-26 12:23发布

问题:

Here is a piece of code destined to check user rights before each UI-router state change. Everything works fine, except the fact that when rights are OK, the transition to the new state (either with $state.go, as below, or with $state.transitionTo), does not seem to do anything at all (the console message is logged but that's all).

angular.module('mymodule', [ /* dependancies */ ])

.run( function($rootScope, $window, $state, AuthManager)
{
    $rootScope.$on('$stateChangeStart',
        function(event, toState, toParams, fromState, fromParams)
        {
            if( ! S.isUserConnected() && toParams.requiresLogIn )
            {
                event.preventDefault();
                AuthManager.openConnectionPane().then( function( data )
                {
                    if( AuthManager.isUserConnected() ) {
                        console.log("This message is correctly printed!");
                        $state.go( toState.name );
                    }
                });
            }
        }
    );
});

Do you have any idea why this does not work?

EDIT:

I have noticed that the HMTL partial coresponding to the state we are transitioning to, is correctly fetched via a GET request, but it never shows: the old HTML stays displayed (the one from the previous state), even if the URL is correctly updated...

EDIT: add the router config code

In the main module file:

//angular.module('mymodule', [ /* dependancies */ ])
.config( $urlRouterProvider ) {
    $urlRouterProvider.otherwise('/home');
}

And in each submodule:

angular.module( 'mymodule.submodule', [ /* dependancies */ ])

.config(function($stateProvider) {
    $stateProvider
        .state('events-overview', {
            url:'/events',
            templateUrl: 'app/events/events-overview.html',
            controller: 'EventsOverviewCtrl'
        })
        .state('events-details', {
            url:'/events/{eventId:int}',
            templateUrl: 'app/events/events-details.html',
            controller: 'EventsDetailsCtrl'
        })
        .state('events-creation', {
            url:'/events/new',
            params: {
                requiresLogIn: true
            }
            templateUrl: 'app/events/events-creation.html',
            controller: 'EventsCreationCtrl'
        })
});

回答1:

I had a similar issue and this is how I solved it:

if( AuthManager.isUserConnected() ) {
   //...
   event.preventDefault();
   $state.go(toState.name, null, {notify: false}).then(function (state) {
      $rootScope.$broadcast('$stateChangeSuccess', state, null);
   });
}

As it's mentioned in other answers, $state.go doesn't work propertly in .run. Following the advises of this thread I ended up working with this workaround

$urlRouterProvider.otherwise(function ($injector) {
   var $state = $injector.get('$state');
   $state.go('/home');
});

Not sure if this could help you, but you could try it. Hope it helps



回答2:

I think your problem will be fixed by doing this :

angular.module('mymodule', [ /* dependancies */ ])

.run( function($rootScope, $window, $state, AuthManager, $timeout)
{
    $rootScope.$on('$stateChangeStart',
        function(event, toState, toParams, fromState, fromParams)
        {
            if( ! S.isUserConnected() && toParams.requiresLogIn )
            {

                AuthManager.openConnectionPane().then( function( data )
                {
                    if( AuthManager.isUserConnected() ) {
                        console.log("This message is correctly printed!");
                         $timeout(function() {
                            event.preventDefault();
                            $state.go(toState.name);
                          });

                    }
                });
            }
        }
    );
});

$state.go does not work correctly in .run this should be a workaround by adding the timeout



回答3:

try putting the event.preventDefault(); bellow the $state.go.

This is where I saw the idea for this suggestion: angularjs app.run doesn't get called with state

So basically:

AuthManager.openConnectionPane().then( function( data ) { if( AuthManager.isUserConnected() ) { console.log("This message is correctly printed!"); $state.go( toState.name ); } }); event.preventDefault();