92

I have an AuthService, which logs in a user, it returns back a user json object. What I want to do is set that object and have all the changes reflected across the application (logged in/logged out state) without having to refresh the page.

How would I accomplish this with AngularJS?

2 Answers 2

180

The easiest way to accomplish this is by using a service. For example:

app.factory( 'AuthService', function() {
  var currentUser;

  return {
    login: function() { ... },
    logout: function() { ... },
    isLoggedIn: function() { ... },
    currentUser: function() { return currentUser; }
    ...
  };
});

You can then reference this in any of your controllers. The following code watches for changes in a value from the service (by calling the function specified) and then syncs the changed values to the scope.

app.controller( 'MainCtrl', function( $scope, AuthService ) {
  $scope.$watch( AuthService.isLoggedIn, function ( isLoggedIn ) {
    $scope.isLoggedIn = isLoggedIn;
    $scope.currentUser = AuthService.currentUser();
  });
});

And then, of course, you can use that information however you see fit; e.g. in directives, in templates, etc. You can repeat this (customized to what you need to do) in your menu controllers, etc. It will all be updated automatically when you change the state on the service.

Anything more specific depends on your implementation.

Sign up to request clarification or add additional context in comments.

12 Comments

@ChrisNicola Actually, in AngularJS all services are singletons. So the service is created the very first time it's requested (i.e. by a controller or another service) and all subsequent requests for it return the exact same instance.
It could be, but as a function we can remove the internals of how we store that information from the public API and into the private API. This makes refactoring later much easier. But the function would still return a boolean.
This might be a stupid question... but what happens if the user refreshes the page - is the login information lost?
@Tomba That's a good question. :-) Indeed the info is lost on refresh. Usually, you'll want to store some session information in a cookie. That session info can also be checked when setting up the AuthService. This helps not only for page refreshes but for someone opening a link in a new tab.
@PixMach You're 100% right about the learning curve. Your question is going to depend a lot of the specific case, but here are some general patterns. Keep separation of concerns: the UI related to initiating a login is separate from the auth itself, which is separate from the state of the auth, which is separate from any menu that may depend on said state. Nav/menu are often best handled by a single controller, and nested states (a la ui-router) and route resolves are a good way to keep auth controls DRY. What you wrote sounds about right.
|
5

I would amend the good response of Josh by adding that, as an AuthService is typically of interest of anyone (say, anyone but the login view should disappear if nobody is logged), maybe a simpler alternative would be to notify interested parties using $rootScope.$broadcast('loginStatusChanged', isLoggedIn); (1) (2), while interested parties (such as controllers) would listen using $scope.$on('loginStatusChanged', function (event, isLoggedIn) { $scope.isLoggedIn = isLoggedIn; }.

(1) $rootScope being injected as an argument of the service

(2) Note that, in the likely case of a asynchronous login operation, you'll want to notify Angular that the broadcast will change things, by including it in a $rootScope.$apply() function.

Now, speaking of keeping the user context in every/many controllers, you might not be happy listening for login changes in everyone of them, and might prefer to listen only in a topmost login controller, then adding other login-aware controllers as children/embedded controllers of this one. This way, the children controller will be able to see the inherited parent $scope properties such as your user context.

1 Comment

Downvoted for incorrect explanation of the factory function. This misunderstanding was already addressed in this comment months before you posted your answer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.