Как отменить событие изменения маршрута в AngularJs?
Мой текущий код
$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
}
});
при этом, даже если проверка не удалась, Angular извлекает следующий шаблон и связанные данные, а затем немедленно переключается на предыдущий вид / маршрут. Я не хочу, чтобы angular извлекал следующий шаблон и данные, если проверка не удалась, в идеале не должно быть window.history.back (). Я даже пробовал event.preventDefault (), но без толку.
javascript
angularjs
Р Арун
источник
источник
$routeChangeStart
вnext
переменной это просто строка , и она не может содержать каких - либо данных (например , вы не можете получить доступ к определенной ранееauthorizedRoles
переменной)$location.path()
и$location.search()
Более полный пример кода с использованием
$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); }); } );
Я не совсем доволен подключением этого к моему корневому контроллеру (контроллеру верхнего уровня). Если есть лучший образец, я хотел бы знать. Я новичок в angular :-)
источник
Решение состоит в том, чтобы транслировать событие notAuthorized и перехватывать его в основной области, чтобы повторно изменить местоположение. Думаю, это не лучшее решение, но у меня оно сработало:
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'); } } }); } ]);
и в моем основном контроллере:
$scope.$on('notAuthorized', function(){ $location.path('/forbidden'); });
Примечание: эта проблема обсуждается на сайте angular, но еще не решена: https://github.com/angular/angular.js/pull/4192
РЕДАКТИРОВАТЬ:
Чтобы ответить на комментарий, вот дополнительная информация о работе LoginService. Он содержит 3 функции:
(*) Моя сессия заполняется при изменении маршрута. Я переопределил метод when () для заполнения пустого сеанса.
Вот код:
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' }); }]);
источник
LoginService.isAuthenticated()
при загрузке первой страницы? Как вы хранитеcurrentUser
? Что произойдет, если пользователь обновит страницу (пользователю нужно снова ввести учетные данные)?Для тех, кто сталкивается с этим, это старый вопрос (по крайней мере, в angular 1.4) вы можете сделать это:
.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() } }) })
источник
Это мое решение, и оно работает для меня, но я не знаю, на правильном ли я пути, потому что я новичок в веб-технологиях.
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 });
источник
я нашел это подходящим
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() }); });
мой пост может помочь кому-то в будущем.
источник
var app=angular .module('myapp', []) .controller('myctrl', function($rootScope) { $rootScope.$on("locationChangeStart", function(event, next, current) { if (!confirm("location changing to:" + next)) { event.preventDefault(); } }) });
источник
В случае, если вам нужно остановить изменение маршрута в
$routeChangeStart
событии (т.е. вы хотите выполнить некоторую операцию на основе следующего маршрута ), введите$route
и внутренний$routeChangeStart
вызов:источник
$route.reload()
должно быть другим, иначе он снова запускает тот же код. Это эквивалент созданияwhile
цикла сtrue
условием.Чтобы поделиться, в моем случае я хочу отложить разрешение маршрута с помощью $ routeChangeStart. У меня есть SomethingService, который должен загрузиться до начала разрешения маршрута (да, болтливое приложение), поэтому у меня есть обещание подождать. Может быть, я нашел взлом ... Разрешение маршрута идет ошибочно, если решение возвращает отклонение. Я нарушил конфигурацию разрешения и исправлю ее позже.
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; } });
источник