Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to redirect in a ui-router resolver?

I am trying to redirect inside a ui-router resolve and wanted to know if there is a way to reroute in a router resolver. Currently this does not work as one would think.

resolver(auth, $state){
   if(!auth.isLoggedIn()){
       $state.go('noLoggedInPath');
   }
}

How does one redirect in a resolver correctly ?

My temp hack is this but I am not comfortable with it.

resolver(auth, $state, $timeout){
   if(!auth.isLoggedIn()){
        $timeout(function () {

             $state.go('noLoggedInPath');
        }, 0);
   }
}
like image 827
Subtubes Avatar asked Apr 22 '15 23:04

Subtubes


3 Answers

Yauheni's answer does work, but to get around the weird timeout thing, you can reject the promise, and catch that in the $stateChangeError event, and do your redirect there. Like so...

state('admin', {   resolve: {     auth: function(UserService, $q, permissionService) {       var deferred = $q.defer();       return UserService.load().then(function(user){         if (permissionService.can(user, {goTo: state})) {           return deferred.resolve({});         } else {           return deferred.reject({redirectTo: 'some_other_state'});         }       });     }   } }); 

And then ui-router always broadcasts "stateChangeError", so you can do something like this..

$rootScope.$on('$stateChangeError', function(evt, to, toParams, from, fromParams, error) {   if (error.redirectTo) {     $state.go(error.redirectTo);   } else {     $state.go('error', {status: error.status})   } }) 
like image 127
bwest87 Avatar answered Oct 02 '22 17:10

bwest87


You can return a promise from your resolver function that will indicate whether to continue navigating to the state or not. If you decide to navigate somewhere else - reject the promise and specify the proper state:

resolver($q, $state, $timeout, auth) {
    var deferred = $q.defer();

    // $timeout is an example; it also can be an xhr request or any other async function
    $timeout(function() {
      if (!auth.isLoggedIn()) {
        // user is not logged, do not proceed
        // instead, go to a different page
        $state.go('noLoggedInPath');
        deferred.reject();
      } else {
        // everything is fine, proceed
        deferred.resolve();
      }
    });

    return deferred.promise;
}

Plunkr here.

UPD: updated code and added plunkr. Looks like it only works if you put it inside a timeout function.

like image 45
Yauheni Leichanok Avatar answered Oct 02 '22 17:10

Yauheni Leichanok


I use this

   function Check($state, $q) {
        var deferred = $q.defer();
        if (condition) {
            deferred.resolve();
        }
        else {
            deferred.reject();
        }
        return deferred.promise.catch(function () { $state.go('path'); });
    }
like image 26
Hikmat G. Avatar answered Oct 02 '22 17:10

Hikmat G.