Search code examples
javascriptangularjsangularjs-scopeangularjs-serviceangularjs-controller

AngularJS: Bind angular service property to scope


Scenario

  • I have a service UserService that maintains the (boolean) sessionStatus of the user.
  • The view conditionally shows [LOGOUT] on ng-show=sessionStatus (i.e. if not logged in (false), no show).
  • sessionStatus of ViewController should therefore always match that of UserService ... right?
  • If you click [LOGOUT] when it's visible, it does some loggy outty things, sessionStatus value changes, and view should update with new outcome of ng-show....

Problem

  1. Currently, clicking logout does not seem to update var UserService.sessionStatus?
  2. How do I keep $scope.sessionStatus updated when UserService.logout() occurs and changes UserService.sessionStatus?
    • How do I map the changing $scope to ng-show?

Files

View

    <a ng-show="sessionStatus" ng-click="logout()">Logout</a>

ViewController

    app.controller('AppController', function($scope, $interval, $http, UserService) {
      $scope.logout = function() { UserService.logout(); }

      // This ain't working
      $scope.$watch(UserService.sessionStatus, function() {
          $scope.sessionStatus = UserService.sessionStatus;
      });
    });

UserService

NB: appUser is an injected global var in the HTML head (a hacky fix until I get session/cookie stuff working properly)

  app.factory('UserService', function($http) {
    var pre;
    var sessionStatus;

    function init() {                   // Logged in  : Logged out             
      pre = appUser.user != undefined ? appUser.user  : { name: 'Logged out', uid: '0' };
      sessionStatus = pre.uid != "0"  ? true          : false;
    }

    function resetSession() { appUser = null; init(); }

    init();

    return {
      sessionStatus: function() { return sessionStatus; }, // update on change!

      logout: function() {
        $http.get("/logout").then(function (data, status, headers, config) {
          resetSession();
        })
      }
    };
  });

Solution

  • Instead of a watch, simply use a scoped function that returns the session status from the service.

    $scope.sessionStatus = function() {
        return userService.sessionStatus();
    };
    

    Your Logout link would look as below:

    <a ng-show="sessionStatus()" ng-click="logout()">Logout</a>
    

    A stripped down Plunker for your functionality: http://plnkr.co/edit/u9mjQvdsvuSYTKMEfUwR?p=preview