AngularJs - annuler l'événement de changement de route
Comment annuler un changement d'itinéraire à AngularJs?
mon code actuel est
$rootScope.$on("$routeChangeStart", function (event, next, current) {
// do some validation checks
if(validation checks fails){
console.log("validation failed");
window.history.back(); // Cancel Route Change and stay on current page
}
});
avec ceci même si la validation échoue angulaire tire le modèle suivant et les données associées et puis passe immédiatement de nouveau à la vue/route précédente. Je ne veux pas qu'angular tire le prochain modèle et les données si la validation échoue, idéalement il ne devrait pas y avoir de fenêtre.histoire.arrière.)( J'ai même essayé l'événement.preventDefault (), mais pas de l'utiliser.
8 réponses
au lieu de $routeChangeStart
utiliser $locationChangeStart
Voici la discussion à ce sujet par les gars d'angularjs: https://github.com/angular/angular.js/issues/2109
Edit 3/6/2018 vous pouvez le trouver dans les documents: https://docs.angularjs.org/api/ng/service / $lieu#event - $locationChangeStart
exemple:
$scope.$on('$locationChangeStart', function(event, next, current) {
if ($scope.form.$invalid) {
event.preventDefault();
}
});
un échantillon de code plus complet, en utilisant $locationChangeStart
// assuming you have a module called app, with a
angular.module('app')
.controller(
'MyRootController',
function($scope, $location, $rootScope, $log) {
// your controller initialization here ...
$rootScope.$on("$locationChangeStart", function(event, next, current) {
$log.info("location changing to:" + next);
});
}
);
Je ne suis pas complètement content de l'accrocher dans mon contrôleur root (contrôleur de haut niveau). Si il y a un meilleur modèle, j'aimerais savoir. Je suis nouveau à l'angle: -)
une solution est de diffuser un événement "non autorisé", et de le saisir dans le but principal de changer de lieu. Je pense que ce n'est pas la meilleure solution, mais ça a fonctionné pour moi:
myApp.run(['$rootScope', 'LoginService',
function ($rootScope, LoginService) {
$rootScope.$on('$routeChangeStart', function (event, next, current) {
var authorizedRoles = next.data ? next.data.authorizedRoles : null;
if (LoginService.isAuthenticated()) {
if (!LoginService.isAuthorized(authorizedRoles)) {
$rootScope.$broadcast('notAuthorized');
}
}
});
}
]);
et dans mon contrôleur principal:
$scope.$on('notAuthorized', function(){
$location.path('/forbidden');
});
Note: il y a une discussion sur ce problème sur site angulaire, pas encore résolu: https://github.com/angular/angular.js/pull/4192
EDIT:
pour répondre au commentaire, voici plus d'informations sur les travaux de LoginService. Il contient 3 fonctions:
- login () (nom trompeur) faire une demande au serveur pour obtenir des informations sur l'utilisateur (précédemment) connecté. Il y a une autre page de connexion qui remplit simplement l'état utilisateur courant dans le serveur (en utilisant SpringSecurity framework). Mes Services Web ne sont pas vraiment apatrides, mais j'ai préféré laisser cette célèbre cadre Gérer ma sécurité .
- isAuthenticated() il suffit de chercher si la Session du client est rempli avec des données, ce qui signifie qu'il a été authentifié avant (*)
- isAuthorized() a traité des droits d'accès (hors de la portée de cette rubrique).
(*) Ma Session est remplie lorsque le changement d'itinéraire. J'ai remplacé alors la méthode when () pour remplir la session vide.
voici le code :
services.factory('LoginService', ['$http', 'Session', '$q',
function($http, Session, $q){
return {
login: function () {
var defer = $q.defer();
$http({method: 'GET', url: restBaseUrl + '/currentUser'})
.success(function (data) {
defer.resolve(data);
});
return defer.promise;
},
isAuthenticated: function () {
return !!Session.userLogin;
},
isAuthorized: function (authorizedRoles) {
if (!angular.isArray(authorizedRoles)) {
authorizedRoles = [authorizedRoles];
}
return (this.isAuthenticated() && authorizedRoles.indexOf(Session.userRole) !== -1);
}
};
}]);
myApp.service('Session', ['$rootScope',
this.create = function (userId,userLogin, userRole, userMail, userName, userLastName, userLanguage) {
//User info
this.userId = userId;
this.userLogin = userLogin;
this.userRole = userRole;
this.userMail = userMail;
this.userName = userName;
this.userLastName = userLastName;
this.userLanguage = userLanguage;
};
this.destroy = function () {
this.userId = null;
this.userLogin = null;
this.userRole = null;
this.userMail = null;
this.userName = null;
this.userLastName = null;
this.userLanguage = null;
sessionStorage.clear();
};
return this;
}]);
myApp.config(['$routeProvider', 'USER_ROLES', function ($routeProvider, USER_ROLES) {
$routeProvider.accessWhen = function (path, route) {
if (route.resolve == null) {
route.resolve = {
user: ['LoginService','Session',function (LoginService, Session) {
if (!LoginService.isAuthenticated())
return LoginService.login().then(function (data) {
Session.create(data.id, data.login, data.role, data.email, data.firstName, data.lastName, data.language);
return data;
});
}]
}
} else {
for (key in route.resolve) {
var func = route.resolve[key];
route.resolve[key] = ['LoginService','Session','$injector',function (LoginService, Session, $injector) {
if (!LoginService.isAuthenticated())
return LoginService.login().then(function (data) {
Session.create(data.id, data.login, data.role, data.email, data.firstName, data.lastName, data.language);
return func(Session, $injector);
});
else
return func(Session, $injector);
}];
}
}
return $routeProvider.when(path, route);
};
//use accessWhen instead of when
$routeProvider.
accessWhen('/home', {
templateUrl: 'partials/dashboard.html',
controller: 'DashboardCtrl',
data: {authorizedRoles: [USER_ROLES.superAdmin, USER_ROLES.admin, USER_ROLES.system, USER_ROLES.user]},
resolve: {nextEvents: function (Session, $injector) {
$http = $injector.get('$http');
return $http.get(actionBaseUrl + '/devices/nextEvents', {
params: {
userId: Session.userId, batch: {rows: 5, page: 1}
},
isArray: true}).then(function success(response) {
return response.data;
});
}
}
})
...
.otherwise({
redirectTo: '/home'
});
}]);
pour quiconque trébuchant sur cette question est une vieille, (au moins dans l'angle 1.4) vous pouvez faire ceci:
.run(function($rootScope, authenticationService) {
$rootScope.$on('$routeChangeStart', function (event, next) {
if (next.require == undefined) return
var require = next.require
var authorized = authenticationService.satisfy(require);
if (!authorized) {
$rootScope.error = "Not authorized!"
event.preventDefault()
}
})
})
C'est ma solution et ça marche pour moi mais je ne sais pas si je suis sur la bonne voie car je suis nouveau dans les technologies web.
var app = angular.module("app", ['ngRoute', 'ngCookies']);
app.run(function($rootScope, $location, $cookieStore){
$rootScope.$on('$routeChangeStart', function(event, route){
if (route.mustBeLoggedOn && angular.isUndefined($cookieStore.get("user"))) {
// reload the login route
jError(
'You must be logged on to visit this page',
{
autoHide : true,
TimeShown : 3000,
HorizontalPosition : 'right',
VerticalPosition : 'top',
onCompleted : function(){
window.location = '#/signIn';
window.setTimeout(function(){
}, 3000)
}
});
}
});
});
app.config(function($routeProvider){
$routeProvider
.when("/signIn",{
controller: "SignInController",
templateUrl: "partials/signIn.html",
mustBeLoggedOn: false
});
dans le cas où vous avez besoin d'arrêter la route de changer dans l'événement $routeChangeStart
(i.e. vous voulez effectuer une certaine opération basée sur la route suivante ), injecter $route
et à l'intérieur $routeChangeStart
appel:
$route.reload()
j'ai trouvé celui-ci pertinent
var myApp = angular.module('myApp', []);
myApp.run(function($rootScope) {
$rootScope.$on("$locationChangeStart", function(event, next, current) {
// handle route changes
$rootScope.error = "Not authorized!"
event.preventDefault()
});
});
mon post peut aider quelqu'un dans le futur.
var app=angular
.module('myapp', [])
.controller('myctrl', function($rootScope) {
$rootScope.$on("locationChangeStart", function(event, next, current) {
if (!confirm("location changing to:" + next)) {
event.preventDefault();
}
})
});