如何在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也会拉出下一个模板和相关数据,然后立即切换回上一个视图/路径。我不希望角度拉下一个模板&如果验证失败,理想情况下应该没有window.history.back()。我甚至尝试过event.preventDefault()但没有用。
答案 0 :(得分:183)
而不是$routeChangeStart
使用$locationChangeStart
以下是来自angularjs家伙的讨论:https://github.com/angular/angular.js/issues/2109
修改3/6/2018 您可以在文档中找到它:https://docs.angularjs.org/api/ng/service/$location#event-$locationChangeStart
示例:
$scope.$on('$locationChangeStart', function(event, next, current) {
if ($scope.form.$invalid) {
event.preventDefault();
}
});
答案 1 :(得分:38)
$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);
});
}
);
我对在我的根控制器(顶级控制器)中挂起它并不是很满意。如果有更好的模式,我很想知道。我是棱角分明的新人: - )
答案 2 :(得分:11)
解决方案是播放“未授权”'事件,并在主要范围内捕获它以重新更改位置。我认为这不是最好的解决方案,但它对我有用:
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');
});
注意:在角点网站上有一些关于这个问题的讨论,还没有解决: 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'
});
}]);
答案 3 :(得分:4)
对于任何磕磕绊绊的人来说,这是一个古老的问题,(至少在角度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()
}
})
})
答案 4 :(得分:1)
这是我的解决方案,它适用于我,但我不知道我是否正确的方式因为我是网络技术的新手。
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
});
答案 5 :(得分:1)
var app=angular
.module('myapp', [])
.controller('myctrl', function($rootScope) {
$rootScope.$on("locationChangeStart", function(event, next, current) {
if (!confirm("location changing to:" + next)) {
event.preventDefault();
}
})
});
答案 6 :(得分:0)
如果你需要停止改变$routeChangeStart
事件的路线(即你想根据下一条路线执行一些操作),请注入$route
并在$routeChangeStart
内调用:
$route.reload()
答案 7 :(得分:0)
我发现了这个相关的
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()
});
});
我的帖子将来可能对某人有帮助。
答案 8 :(得分:0)
在我的情况下,我只想与$ 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;
}
});