Jak anulować zdarzenie zmiany trasy w AngularJs?
Mój obecny kod to
$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
}
});
z tym, nawet jeśli walidacja się nie powiedzie, Angular pobiera następny szablon i powiązane dane, a następnie natychmiast przełącza się z powrotem do poprzedniego widoku / trasy. Nie chcę, aby angular ściągał następny szablon i dane, jeśli walidacja się nie powiedzie, najlepiej byłoby, gdyby nie było okna.history.back (). Próbowałem nawet event.preventDefault (), ale bez sensu.
javascript
angularjs
R Arun
źródło
źródło
$routeChangeStart
znext
zmienną jest po prostu ciągiem i nie może zawierać żadnych danych (na przykład nie można dostęp do zdefiniowanej wcześniejauthorizedRoles
zmiennej)$location.path()
i$location.search()
Bardziej kompletny przykład kodu przy użyciu
$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); }); } );
Nie jestem do końca zadowolony z podłączenia tego do mojego kontrolera głównego (kontrolera najwyższego poziomu). Jeśli istnieje lepszy wzór, chciałbym wiedzieć. Jestem nowy w Angular :-)
źródło
Rozwiązaniem jest transmitowanie zdarzenia „notAuthorized” i przechwytywanie go w głównym zakresie w celu ponownej zmiany lokalizacji. Myślę, że to nie jest najlepsze rozwiązanie, ale u mnie zadziałało:
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'); } } }); } ]);
aw moim głównym kontrolerze:
$scope.$on('notAuthorized', function(){ $location.path('/forbidden'); });
Uwaga: na stronie kątowej jest dyskusja na temat tego problemu, jeszcze nie rozwiązana: https://github.com/angular/angular.js/pull/4192
EDYTOWAĆ:
Aby odpowiedzieć na komentarz, poniżej znajduje się więcej informacji o działaniu usługi LoginService. Zawiera 3 funkcje:
(*) Moja sesja jest zapełniana po zmianie trasy. Zastąpiłem metodę then when (), aby zapełniać sesję, gdy jest pusta.
Oto kod:
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' }); }]);
źródło
LoginService.isAuthenticated()
przy ładowaniu pierwszej strony? Jak przechowujeszcurrentUser
? Co się stanie, jeśli użytkownik odświeży stronę (użytkownik będzie musiał ponownie wprowadzić poświadczenia)?Dla każdego, kto się na to natknie, jest to stare pytanie (przynajmniej w kątowym 1.4), możesz zrobić to:
.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() } }) })
źródło
To jest moje rozwiązanie i działa dla mnie, ale nie wiem, czy jestem na dobrej drodze, ponieważ jestem nowy w technologiach internetowych.
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 });
źródło
znalazłem ten odpowiedni
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() }); });
mój post może pomóc komuś w przyszłości.
źródło
var app=angular .module('myapp', []) .controller('myctrl', function($rootScope) { $rootScope.$on("locationChangeStart", function(event, next, current) { if (!confirm("location changing to:" + next)) { event.preventDefault(); } }) });
źródło
W przypadku, gdy musisz zatrzymać zmianę trasy w
$routeChangeStart
przypadku zdarzenia (tj. Chcesz wykonać jakąś operację w oparciu o następną trasę ), wstrzyknij$route
i$routeChangeStart
wywołanie wewnętrzne :źródło
$route.reload()
musi być inny, w przeciwnym razie ponownie uruchamia ten sam kod. Jest to odpowiednik tworzeniawhile
pętli ztrue
warunkiem.Tylko po to, aby udostępnić, w moim przypadku chcę opóźnić rozpoznanie trasy za pomocą $ routeChangeStart. Mam usługę SomethingService, która musi zostać załadowana przed rozpoczęciem rozwiązywania trasy (tak, rozmowa aplikacja), więc mam obietnicę, na którą muszę poczekać. Może znalazłem hack ... Rozwiązanie trasy jest błędne, jeśli rozwiązanie zwraca odrzucenie. Zepsułem konfigurację rozwiązania i naprawiam to później.
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; } });
źródło