¿Cómo cancelo el evento de cambio de ruta en AngularJs?
Mi código actual es
$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
}
});
con esto, incluso si la validación falla, Angular extrae la siguiente plantilla y los datos asociados y luego vuelve inmediatamente a la vista / ruta anterior. No quiero que angular extraiga la siguiente plantilla y datos si falla la validación, idealmente no debería haber window.history.back (). Incluso probé event.preventDefault () pero no utilicé.
javascript
angularjs
R Arun
fuente
fuente
$routeChangeStart
lanext
variable es solo una cadena y no puede contener ningún dato (por ejemplo, no puede acceder a laauthorizedRoles
variable anterior definida )$location.path()
y$location.search()
Una muestra de código más completa, usando
$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); }); } );
No estoy completamente satisfecho con conectar esto en mi controlador raíz (controlador de nivel superior). Si hay un patrón mejor, me encantaría saberlo. Soy nuevo en angular :-)
fuente
Una solución es transmitir un evento 'notAuthorized' y capturarlo en el alcance principal para volver a cambiar la ubicación. Creo que no es la mejor solución, pero funcionó para mí:
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'); } } }); } ]);
y en mi controlador principal:
$scope.$on('notAuthorized', function(){ $location.path('/forbidden'); });
Nota: hay una discusión sobre este problema en el sitio angular, aún no resuelto: https://github.com/angular/angular.js/pull/4192
EDITAR:
Para responder al comentario, aquí hay más información sobre los trabajos de LoginService. Contiene 3 funciones:
(*) Mi sesión se completa cuando cambia la ruta. He anulado el método when () para completar la sesión cuando está vacía.
Aquí está el código:
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' }); }]);
fuente
LoginService.isAuthenticated()
al cargar la primera página? ¿Cómo estás almacenandocurrentUser
? ¿Qué sucede si el usuario actualiza la página (el usuario necesita volver a ingresar las credenciales)?Para cualquiera que se encuentre con esto es una vieja pregunta, (al menos en angular 1.4) puede hacer esto:
.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() } }) })
fuente
Esta es mi solución y funciona para mí, pero no sé si estoy en el camino correcto porque soy nuevo en las tecnologías 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 });
fuente
Encontré este relevante
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() }); });
mi publicación puede ayudar a alguien en el futuro.
fuente
var app=angular .module('myapp', []) .controller('myctrl', function($rootScope) { $rootScope.$on("locationChangeStart", function(event, next, current) { if (!confirm("location changing to:" + next)) { event.preventDefault(); } }) });
fuente
En caso de que necesite evitar que la ruta cambie en el
$routeChangeStart
evento (es decir, si desea realizar alguna operación basada en la siguiente ruta ), inyecte$route
y$routeChangeStart
llame internamente:fuente
$route.reload()
debe ser diferente o, de lo contrario, se está ejecutando el mismo código nuevamente. Este es el equivalente a crear unwhile
bucle contrue
la condición.Solo para compartir, en mi caso quiero retrasar la resolución de la ruta con $ routeChangeStart. Tengo un SomethingService que debe cargarse antes de que comience la resolución de la ruta (sí, aplicación habladora), por lo tanto, tengo la promesa de esperar. Quizás encontré un truco ... La resolución de la ruta falla si una resolución devuelve un rechazo. Rompí la configuración de resolución y la soluciono más tarde.
var rejectingResolve = { cancel: function ($q){ // this will cancel $routeChangeStart return $q.reject(); } } $rootScope.$on("$routeChangeStart", function(event, args, otherArgs) { var route = args.$$route, originalResolve = route.resolve; if ( ! SomethingService.isLoaded() ){ SomethingService.load().then(function(){ // fix previously destroyed route configuration route.resolve = originalResolve; $location.search("ts", new Date().getTime()); // for redirections $location.replace(); }); // This doesn't work with $routeChangeStart: // we need the following hack event.preventDefault(); // This is an hack! // We destroy route configuration, // we fix it back when SomethingService.isLoaded route.resolve = rejectingResolve; } });
fuente