J'essaie de rediriger à l'intérieur d'une résolution de routeur ui et je voulais savoir s'il existe un moyen de rediriger un résolveur de routeur. Actuellement, cela ne fonctionne pas comme on pourrait le penser.
resolver(auth, $state){
if(!auth.isLoggedIn()){
$state.go('noLoggedInPath');
}
}
Comment on redirige dans un résolveur correctement?
Mon temp hack est ceci mais je ne suis pas à l'aise avec ça.
resolver(auth, $state, $timeout){
if(!auth.isLoggedIn()){
$timeout(function () {
$state.go('noLoggedInPath');
}, 0);
}
}
Vous pouvez retourner une promesse de votre fonction resolver
qui indiquera si vous souhaitez continuer à naviguer vers l'état ou non. Si vous décidez de naviguer ailleurs, rejetez la promesse et spécifiez le bon état:
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 ici .
UPD: code mis à jour et ajouté plunkr. On dirait que cela ne fonctionne que si vous le mettez dans une fonction de délai d'attente.
La réponse de Yauheni fonctionne, mais pour contourner le problème du délai d'attente étrange, vous pouvez rejeter la promesse et la capturer dans l'événement $ stateChangeError, et y effectuer votre redirection. Ainsi...
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'});
}
});
}
}
});
Et puis ui-router diffuse toujours "stateChangeError", vous pouvez donc faire quelque chose comme ça.
$rootScope.$on('$stateChangeError', function(evt, to, toParams, from, fromParams, error) {
if (error.redirectTo) {
$state.go(error.redirectTo);
} else {
$state.go('error', {status: error.status})
}
})
Je l'utilise
function Check($state, $q) {
var deferred = $q.defer();
if (condition) {
deferred.resolve();
}
else {
deferred.reject();
}
return deferred.promise.catch(function () { $state.go('path'); });
}
C'est ce que je fais en réalité et je ne trouve pas de meilleure solution
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);
}
}
Je pense qu'une réponse beaucoup plus claire est de retourner une promesse déjà rejetée comme ceci:
resolver(auth, $state, $q){
if(!auth.isLoggedIn()){
$state.go('noLoggedInPath');
// Return rejected promise
return $q.reject();
}
return true;
}
Utiliser résolus pour cela n'a pas vraiment fonctionné pour moi. J'ai adapté la logique de this post pour exécuter une fonction de redirection sur la propriété data de l 'objet state. Vous pouvez ensuite accéder à l'événement $ stateChangeStart sur $ rootScope à partir du bloc d'exécution du module et utiliser la méthode invoke du service d'injecteur pour modifier l'état en fonction des conditions spécifiées. Fonctionne bien sur tous les modules.
Vous pouvez utiliser les promesses du résolveur avec la configuration redirectTo
redirectTo: function($transition$) {
return $transition$.injector().getAsync('isNew').then(function(isNew) {
return isNew ? 'estate.edit' : 'estate.view';
});
},