0

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: '/'
        });



    }]);

3 Answers3

0

You would add an event handler in the Service to $rootScope instead of $scope.

Also it would be much better if you would add the $routeChangeSuccess in the ".run" section so all the pages can be monitored from one point rather than adding it in every controller

Saneesh B
  • 572
  • 4
  • 13
0

You need to listen $rootScope instead of $scope.

And I think it's better to call that listener on the init of wrapped service, for instance (Services are singletons, so it will be run once you will inject it to any controller).

angular.module('lmsApp')

.service('stateService', ['$rootScope', function ($rootScope) {
    $rootScope.$on('$locationChangeStart', (event, next, current) => {
        // do your magic
    });

}]);
Kanso Code
  • 7,479
  • 5
  • 34
  • 49
0

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
}); 
Stefan.B
  • 136
  • 1
  • 5