javascript - directivas - AngularJs: cancela el evento de cambio de ruta
ng-href angular 4 (8)
Un ejemplo de código más completo, 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 del todo contento 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 :-)
¿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 cambia inmediatamente a la vista / ruta anterior. No deseo que angular tire la siguiente plantilla y datos si la validación falla, idealmente no debería haber window.history.back (). Incluso intenté event.preventDefault () pero no uso.
En caso de que necesite evitar que la ruta cambie en el evento $routeChangeStart
(es decir, si desea realizar alguna operación según la siguiente ruta ), ingrese $route
y dentro de $routeChangeStart
call:
$route.reload()
En lugar de $routeChangeStart
use $locationChangeStart
Aquí está la discusión sobre esto de los chicos de angularjs: https://github.com/angular/angular.js/issues/2109
Edite 06/03/2018 Puede encontrarlo en los documentos: https://docs.angularjs.org/api/ng/service/$location#event-$locationChangeStart
Ejemplo:
$scope.$on(''$locationChangeStart'', function(event, next, current) {
if ($scope.form.$invalid) {
event.preventDefault();
}
});
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.
Esta es mi solución y funciona para mí, pero no sé si estoy en el camino correcto porque soy nuevo en 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
});
Para cualquiera que se tropiece 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()
}
})
})
Una solución es transmitir un evento ''no autorizado'' 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 alguna 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 el funcionamiento de LoginService. Contiene 3 funciones:
- login () (el nombre es engañoso) haga una solicitud al servidor para obtener información sobre el usuario (previamente) conectado. Hay otra página de inicio de sesión que completa el estado actual del usuario en el servidor (utilizando el marco SpringSecurity). Mis servicios web no son verdaderamente apátridas, pero preferí dejar que ese famoso framework manejara mi seguridad.
- isAuthenticated () solo busca si la sesión del cliente está llena de datos, lo que significa que se ha autenticado antes (*)
- isAuthorized () maneja los derechos de acceso (fuera del alcance de este tema).
(*) Mi sesión se llena cuando cambia la ruta. He reemplazado 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''
});
}]);
var app=angular
.module(''myapp'', [])
.controller(''myctrl'', function($rootScope) {
$rootScope.$on("locationChangeStart", function(event, next, current) {
if (!confirm("location changing to:" + next)) {
event.preventDefault();
}
})
});