Как перенаправить в резольвере 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);
}
}
Ответы
Ответ 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 из блока запуска модуля и использовать метод вызова службы инжектора для изменения состояния на основе заданных условий. Хорошо работает и с модулями.