programing tip

AngularJs-경로 변경 이벤트 취소

itbloger 2020. 9. 11. 07:47
반응형

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  

}
});

유효성 검사가 실패하더라도 Angular는 다음 템플릿과 관련 데이터를 가져온 다음 즉시 이전보기 / 경로로 다시 전환합니다. 유효성 검사가 실패하면 angular가 다음 템플릿 및 데이터를 가져 오는 것을 원하지 않습니다. 이상적으로는 window.history.back ()이 없어야합니다. event.preventDefault () 시도했지만 사용하지 않았습니다.


$routeChangeStart사용 대신$locationChangeStart

다음은 angularjs 녀석들의 토론입니다 : https://github.com/angular/angular.js/issues/2109

2018 년 3 월 6 일 편집 문서에서 찾을 수 있습니다 : https://docs.angularjs.org/api/ng/service/$location#event-$locationChangeStart

예:

$scope.$on('$locationChangeStart', function(event, next, current) {
    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); 
      });
    }
  );

나는 이것을 루트 컨트롤러 (최상위 컨트롤러)에 연결하는 것이 완전히 만족스럽지 않습니다. 더 나은 패턴이 있다면 알고 싶습니다. 나는 각도가 처음이다 :-)


해결책은 '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');
    });

참고 : 각도 사이트에서이 문제에 대한 토론이 아직 해결되지 않았습니다. https://github.com/angular/angular.js/pull/4192

편집하다:

의견에 답하기 위해 LoginService 작동에 대한 자세한 정보가 있습니다. 3 가지 기능이 있습니다.

  1. login () (이름은 오해의 소지가 있음) (이전에) 로그인 한 사용자에 대한 정보를 얻기 위해 서버에 요청합니다. 서버에 현재 사용자 상태를 채우는 또 다른 로그인 페이지가 있습니다 (SpringSecurity 프레임 워크 사용). 내 웹 서비스는 실제로 상태 비 저장이 아니지만 유명한 프레임 워크가 내 보안을 처리하도록하는 것을 선호했습니다.
  2. isAuthenticated () 클라이언트 세션이 데이터로 채워져 있는지 검색합니다. 즉, (*) 전에 인증되었음을 의미합니다.
  3. 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'
    });
}]);

이것에 걸려 넘어지는 사람에게는 오래된 질문입니다 (적어도 각도 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()
            }
        })
      })

This is my solution and it works for me but i don't know if i am on the right way cause i am new to web technologies.

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 app=angular
    .module('myapp', [])
    .controller('myctrl', function($rootScope) {
        $rootScope.$on("locationChangeStart", function(event, next, current) {
        if (!confirm("location changing to:" + next)) { 
            event.preventDefault();
        }
    })
});

In case you need to do stop the route from changing in the $routeChangeStart event (i.e. you want to perform some operation based on the next route), inject $route and inside $routeChangeStart call:

$route.reload()

i found this one relevant

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()   
    });
});

my post may help some one in future.

참고URL : https://stackoverflow.com/questions/16344223/angularjs-cancel-route-change-event

반응형