Naresh
Naresh

Reputation: 25793

AngularJS - How to expose service properties

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>

Upvotes: 4

Views: 3702

Answers (2)

Mindastic
Mindastic

Reputation: 4121

Instead of doing this

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

Try doing 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. That will check isAuthenticated value and return it everytime you call service.isAuthenticated(). You should do the same with user. You should call service.user().

Upvotes: 0

Agop
Agop

Reputation: 1917

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.

Upvotes: 5

Related Questions