AngularJs – 取消路线变更事件
如何取消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 } });
即使validation失败,Angular也会提取下一个模板和关联的数据,然后立即切换回上一个视图/路由。 如果validation失败,我不希望拉动下一个模板和数据,理想情况是不应该有window.history.back()。 我什至试过event.preventDefault()但没用。
而不是$routeChangeStart
使用$locationChangeStart
以下是来自angularjs家伙的讨论: https : //github.com/angular/angular.js/issues/2109
例:
$scope.$on('$locationChangeStart', function(event) { if ($scope.form.$invalid) { event.preventDefault(); } });
一个更完整的代码示例,使用$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:-)
一个解决scheme是广播一个“notAuthorized”事件,并将其捕获到主要范围中以重新更改位置。 我认为这不是最好的解决scheme,但它对我有效:
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 site上有一些关于这个问题的讨论,还没有解决: https : //github.com/angular/angular.js/pull/4192
编辑:
要回答评论,这里是关于LoginService作品的更多信息。 它包含3个function:
- login()(名称具有误导性)请求服务器获取有关(以前)logging的用户的信息。 还有另一个login页面,它只是填充服务器中的当前用户状态(使用SpringSecurity框架)。 我的Web服务并不是真正的无状态,但我更愿意让那个着名的框架来处理我的安全。
- isAuthenticated()只是search客户端会话是否充满数据,这意味着它已经被authentication之前(*)
- isAuthorized()处理访问权限(超出了本主题的范围)。
(*)当路由改变时,我的会话被填充。 我有覆盖然后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' }); }]);
对于任何人来说,这是一个老问题,(至less在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() } }) })
这是我的解决scheme,它适用于我,但我不知道我是否正确的方式,因为我是新的networking技术。
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 });
如果你需要停止改变$routeChangeStart
事件的path(即你想执行一些基于下一个路由的操作 ),注入$route
并在$routeChangeStart
调用中:
$route.reload()
我发现这一个有关
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() }); });
我的post可能会帮助一些未来。
var app=angular .module('myapp', []) .controller('myctrl', function($rootScope) { $rootScope.$on("locationChangeStart", function(event, next, current) { if (!confirm("location changing to:" + next)) { event.preventDefault(); } }) });
- Ng型不更新控制器值
- 使用templateUrl进行unit testingAngularJS指令
- AngularJS下拉指令在外部点击时隐藏
- 如何在使用茉莉花进行unit testing时在AngularJS中模拟一项服务?
- AngularJS intellisense不适用于Visual Studio 2015
- 如何在一个Angularexpression式中将stringparsing为Int?
- Angularjs – ng-cloak / ng-show元素闪烁
- $在指令testing中应用vs $摘要
- AngularJS风格指南 – Todd Motto vs John Papa vs Minko Gechev