Search code examples
angularjsangularjs-serviceangularjs-controller

How to keep track of current user in angularJS controllers?


factory / service:

  angular.module('phoenix-template')
  .factory('User', ['$http', function($http){

      function current(){
        $http.get('http://localhost:4000/api/current_user').then(function(res){
          return res.data;
        })
    }

    this.currentUser = current();

  }]);
})();

controller:

 (function(){
  'use strict';

  angular.module('phoenix-template')
  .controller('NavCtrl', ['$scope','User', function($scope, User){

    $scope.currentUser = User.currentUser;

    $scope.$watch( 'currentUser', function () {
          User.currentUser = $scope.currentUser;
      });

  }]);
})();

I'm keeping track of the current user in the backend, but I want to track my current user in angular across controllers For display purposes, etc..

But, I"m obviously going about this wrong..

Tips, help, much appreciated.


Solution

  • I believe where you are getting confused is that factory and service are not the same in angular.

    • A factory is created on every injection
    • a service is a singleton and is only created once for the lifetime of the angular app.

    The service, in this case, is the best choice to inject into your controllers. The first one to access it will materialize the user data from your server. The rest of the controllers that make use of the service will then use the same service instance so there is no overhead of going to the server for each controller.

    Here is the code. The service retrieves the user using a function but persists the result to a local field, this way it is only ever called once. Your controller can then call the function to retrieve it (or even access the field directly if you add some checking logic).

    (function(){
        angular.module('phoenix-template')
          .service('ngUserService', ['$http', function($http){
    
            var me = this;
            function getUser(callback) {
                // if the user has already been retrieved then do not do it again, just return the retrieved instance
                if(me.currentUser)
                    calback(me.currentUser);
                // retrieve the currentUser and set it as a property on the service
                $http.get('http://localhost:4000/api/current_user').then(function(res){
                  // set the result to a field on the service
                  me.currentUser = res.data;
                  // call the callback with the retrieved user
                  callback(me.currentUser);
                });
            }
            return {getUser:getUser}
          }]);
        })();
    

    Controller code

        (function(){
          'use strict';
    
          angular.module('phoenix-template')
          .controller('NavCtrl', ['$scope','ngUserService', function($scope, ngUserService){
            // call to get the user and set it to your scope variable
            ngUserService.getUser(function(user){$scope.currentUser = user;});
    
      }]);
    })();