I am having a hard time exposing properties from an Angular service. In the example below, I am exposing two properties in authService: isAuthenticated and user. However when isAuthenticated changes, it is not picked up by the HomeController. Can someone help me understand where I am going wrong?
(function() {
    'use strict';
    // Define the 'app' module
    angular.module('app', []);
    // Use the 'app' module
    angular
        .module('app')
        .controller('LoginController', LoginController)
        .controller('HomeController', HomeController)
        .factory('authService', authService);
    // ----- LoginController -----
    LoginController.$inject = ['authService'];
    function LoginController(authService) {
        var vm = this;
        vm.username = null;
        vm.password = null;
        vm.login = login;
        function login() {
            authService.login(vm.username, vm.password);
        }
    }
    // ----- HomeController -----
    HomeController.$inject = ['$scope', 'authService'];
    function HomeController($scope, authService) {
        var vm = this;
        vm.user = null;
        $scope.$watch(
            function() { return authService.isAuthenticated; },
            function() {
                console.log('HomeController: isAuthenticated changed');
                vm.user = authService.user;
            }
        );
    }
    // ----- authService -----
    function authService() {
        var isAuthenticated = false;
        var user = { username: 'jdoe', location: 'Dreamland' };
        var service = {
            login: login,
            isAuthenticated: isAuthenticated,
            user: user
        };
        return service;
        function login(username, password) {
            user = {
                username: username,
                location: 'Boston'
            };
            isAuthenticated = true;
            console.log('authService: isAuthenticated changed');
        }
    }
})();
Here's the index.html file:
<!DOCTYPE html>
<html data-ng-app="app" ng-strict-di>
<head>
    <meta charset="utf-8">
    <title>AngularJS Minimal Template</title>
    <link rel="stylesheet" href="app.css">
</head>
<body>
    <div ng-controller="LoginController as vm">
        <form name="loginForm" ng-submit="vm.login()">
            <label>Username: </label>
            <input type="text" name="username" ng-model="vm.username">
            <label>Password: </label>
            <input type="password" name="password" ng-model="vm.password">
            <button type="submit">Login</button>
        </form>
    </div>
    <div ng-controller="HomeController as vm">
        <h1>{{vm.user.username}}</h1>
        <h2>{{vm.user.location}}</h2>
    </div>
    <!-- JavaScript at the bottom for fast page loading -->
    <script src="lib/angular.js"></script>
    <script src="app.js"></script>
</body>
</html>
                When you do this:
var service = {
    login: login,
    isAuthenticated: isAuthenticated,
    user: user
};
You're creating copies of login, isAuthenticated, and user (although user is a reference to the same object).
Then, when you do this:
function login(username, password) {
    user = {
        username: username,
        location: 'Boston'
    };
    isAuthenticated = true;
    console.log('authService: isAuthenticated changed');
}
You are reassigning the local user variable to a new object and the local isAuthenticated variable to true. Your service object still refers to the old values of these variables.
The most straight forward way to fix this is to assign directly to your service variables:
function login(username, password) {
    service.user = {
        username: username,
        location: 'Boston'
    };
    service.isAuthenticated = true;
    console.log('authService: isAuthenticated changed');
}
This way, the service variables will be updated, and should be reflected anywhere that the service is used. In this scenario, you don't need the local variables anymore - the service object already houses them. Use local variables for private, unexposed variables.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With