Подтвердить что ты не робот

Как перенаправить в резольвере ui-router?

Я пытаюсь перенаправить внутри решения ui-router и хотел бы знать, есть ли способ перенаправления в маршрутизаторе. В настоящее время это не работает, как можно было бы подумать.

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

Как правильно перенаправить в распознаватель?

Мой временный взлом - это, но мне это не удобно.

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

             $state.go('noLoggedInPath');
        }, 0);
   }
}
4b9b3361

Ответ 1

Вы можете вернуть обещание от своей функции resolver, которая будет указывать, продолжать ли переход к состоянию или нет. Если вы решите перемещаться в другом месте - отклоните обещание и укажите правильное состояние:

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 здесь.

UPD: обновлен код и добавлен plunkr. Похоже, он работает, только если вы поместили его в функцию тайм-аута.

Ответ 2

Ответ Yauheni работает, но чтобы обойти странный тайм-аут, вы можете отклонить обещание, поймать его в событии $ stateChangeError и выполнить там свое перенаправление. Вот так...

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'});
        }
      });
    }
  }
});

А затем ui-router всегда передает "stateChangeError", так что вы можете сделать что-то подобное..

$rootScope.$on('$stateChangeError', function(evt, to, toParams, from, fromParams, error) {
  if (error.redirectTo) {
    $state.go(error.redirectTo);
  } else {
    $state.go('error', {status: error.status})
  }
})

Ответ 3

Я использую этот

   function Check($state, $q) {
        var deferred = $q.defer();
        if (condition) {
            deferred.resolve();
        }
        else {
            deferred.reject();
        }
        return deferred.promise.catch(function () { $state.go('path'); });
    }

Ответ 4

Это то, что я на самом деле делаю, и я не могу найти лучшее решение

resolver($q, $timeout, myService) {
    if(!areParameterValuesValid() || !isEverythingLogicallyOk()){
        var deferred = $q.defer();
        $timeout(function() {
            $state.go('somewhere');
            deferred.reject();
        });
        return deferred.promise;
    } else {
        return myService.loadSomething(passingSomeParams);
    }        
}

Ответ 5

Я думаю, что гораздо более чистый ответ - вернуть уже отвергнутое обещание так:

resolver(auth, $state, $q){
   if(!auth.isLoggedIn()){
       $state.go('noLoggedInPath');
       
       // Return rejected promise
       return $q.reject();
   }
   return true;
}

Ответ 6

Вы можете использовать resolver promises с конфигурацией redirectTo

   redirectTo: function($transition$) {
      return $transition$.injector().getAsync('isNew').then(function(isNew) {
        return isNew ? 'estate.edit' : 'estate.view';
      });
    },

Ответ 7

Использование разрешений для этого не совсем сработало для меня. Я адаптировал логику от этот пост для выполнения функции перенаправления на data свойство объекта состояния. Затем вы можете использовать событие $stateChangeStart на $rootScope из блока запуска модуля и использовать метод вызова службы инжектора для изменения состояния на основе заданных условий. Хорошо работает и с модулями.