AngularJS - How to Expose Service Properties

I'm having a hard time exposing the properties of an Angular service. In the example below, I am exposing two properties in authService

: isAuthenticated

and user

. However, when isAuthenticated

it does change, it doesn't get picked up HomeController

. Can anyone help me understand where I am 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 is 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>

      

+3


source to share


2 answers


When you do this:

var service = {
    login: login,
    isAuthenticated: isAuthenticated,
    user: user
};

      

You are making copies login

, isAuthenticated

and user

(although it 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 variable user

to the new object and the local variable isAuthenticated

to true

. Your object service

is still referring to the old values โ€‹โ€‹of these variables.

The easiest 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 wherever the service is used. In this case, you no longer need local variables - the service object already hosts them. Use local variables for private, unexposed variables.

+4


source


Instead of this

var service = {
            login: login,
            isAuthenticated: isAuthenticated,
            user: user
        };

      

Try to do this



var service = {
            login: login,
            isAuthenticated: function() { return isAuthenticated; },
            user: function() { return user; }
        };

      

Then you need to call it as a function not as a value. This will check for the value isAuthenticated

and return it every time you call service.isAuthenticated()

. You must do the same with user

. You have to call service.user()

.

0


source







All Articles