Franchette Camoro Franchette Camoro - 3 months ago 18
AngularJS Question

Detect route change in an Angular service

I'm trying to create a service to check if a certain route needs a user to be logged in to access the page. I have a working code but I want to place the $scope.$on('routeChangeStart) function inside the service. I want to place it in a service because I want to use it in multiple controllers. How do I go about this?

Current code:

profileInfoCtrl.js

angular.module('lmsApp', ['ngRoute'])

.controller('profileInfoCtrl', ['$scope', '$location', ' 'pageAuth', function($scope, $location, pageAuth){

//I want to include this in canAccess function
$scope.$on('$routeChangeStart', function(event, next) {

pageAuth.canAccess(event, next);
});
}]);


pageAuth.js

angular.module('lmsApp')

.service('pageAuth', ['$location', function ($location) {

this.canAccess = function(event, next) {

var user = firebase.auth().currentUser;


//requireAuth is a custom route property
if (next.$$route.requireAuth && user == null ) {

event.preventDefault(); //prevents route change
alert("You must be logged in to access page!");

}
else {
console.log("allowed");
}

}

}]);


routes.js

angular.module('lmsApp')
.config(['$routeProvider', '$locationProvider', function($routeProvider, $locationProvider){
$routeProvider

.when('/admin', {
templateUrl: 'view/admin.html',
css: 'style/admin.css',
controller: 'adminCtrl',
requireAuth: true //custom property to prevent unauthenticated users
})

.otherwise({
redirectTo: '/'
});



}]);

Answer

By using $routeChangeStart, you are listening to a broadcast sent by $routeProvider on every change of the route. I don't think you need to call it in multiple places ( controllers ), just to check this.
In your service:

angular.module('lmsApp')
.service('pageAuth', ['$location', function ($location) {
var canAccess = function(event,next,current){

var user = firebase.auth().currentUser;
//requireAuth is a custom route property
    if (next.$$route.requireAuth && user == null ) {

      event.preventDefault(); //prevents route change
      alert("You must be logged in to access page!");

    }
    else {
      console.log("allowed");
    }

}

$rootScope.$on('$routeChangeStart',canAccess); 
}]);  

And then inject your service in the .run() part of your application. This will ensure the check will be done automatically ( by the broadcast as mentioned earlier ).
In you config part :

angular.module('lmsApp')
    .run(function runApp(pageAuth){
 //rest of your stuff
});