Search code examples
angularjscontrollersfactories

Angular 1.3.9 | Service does not update in controller 1, when change in controller 2


thank you in advance as always. I am new to Angular and trying to learn by building a todoapp from a tutorial that is gradually getting more complicated.

The challenge I am having right now is trying to understand the best way to set a global variable, isLoggedIn, that will get updated when the user logs in via passport and the state can be shared between controllers.

Here is my code:

var todoApp = angular.module('todoApp', []);

todoApp.service('TodoFactory', function() {

this.isLoggedInGlobal = false;

});



todoApp.controller('mainController', ['$scope', '$http', 'TodoFactory', function($scope, $http, TodoFactory) {
    $scope.formData = {due: new Date()};;
    $scope.isLoggedInGlobal = TodoFactory.isLoggedInGlobal;
    $scope.todoData = {deleted: false};

        $scope.getUserTodos = function() {
        $http.get('/api/todos/users')
            .success(function(data) {
              console.log(data)
                $scope.todos = data;
                $scope.isLoggedInGlobal = true;
            })
            .error(function(data) {
                console.log('Error: ' + data);
            });
          }

    // when submitting the add form, send the text to the node API
    $scope.createTodo = function() {
        $http.post('/api/todos', $scope.formData)
            .success(function(data) {
                $scope.formData = {}; // clear the form so our user is ready to enter another
                //$scope.todos = data; no longer needed in favor of the below function
                $scope.getUserTodos();
                console.log(data);
            })
            .error(function(data) {
                console.log('Error: ' + data);
            });
    };

    // delete a todo after checking it
    $scope.deleteTodo = function(id) {
        $http.delete('/api/todos/' + id)
            .success(function(data) {
              //$scope.todos = data; no longer needed in favor of the below function
              $scope.getUserTodos();
                console.log(data);
            })
            .error(function(data) {
                console.log('Error: ' + data);
            });
    };

        $scope.markComplete = function(id) {
        $http.get('/api/todos/complete/' + id)
            .success(function(data) {
              $scope.deleted = true;
              //$scope.todos = data; no longer needed in favor of the below function
              $scope.getUserTodos();
                console.log(data);
            })
            .error(function(data) {
                console.log('Error: ' + data);
            });
    };

  }]);

todoApp.controller('userController', ['$scope', '$http', 'TodoFactory', function($scope, $http, TodoFactory) {
	$scope.loginData = {username: 'taylorackley@gmail.com', password: 'Vb578Vb578!'};
    $scope.welcome = "Hello "
    $scope.isLoggedInGlobal = TodoFactory.isLoggedInGlobal;

    // Auth Functions via passport.
        $scope.loginUser = function() {
        $http.post('/api/users/login', $scope.loginData)
            .success(function(data) {
                $scope.loginData = {}; // clear the form so our user is ready to enter another
                $scope.user = data;
                console.log($scope.isLoggedInGlobal);
                console.log(TodoFactory.isLoggedInGlobal);
                $scope.isLoggedInGlobal = true;
                TodoFactory.isLoggedInGlobal = true;
                console.log($scope.isLoggedInGlobal);
                console.log(TodoFactory.isLoggedInGlobal);
                console.log(data);
                $scope.getUserTodos()
              })

            .error(function(data) {
                console.log('Error: ' + data);
            });

    };

  • You can see where I inject the service into the controllers and set is as a scope variable.
  • WHen the login function gets called on the userController, the user controller $scope variable gets updated to true... the mainController variable does not not.
  • Of course there is a work around by updating the scope variable in the mainController... but that defauts the point of having a global variable.
  • I also tried a simple factory returning both a simple variable and a different way as a function.:

todoApp.factory('mainFactory', function($scope) {

  var isLoggedInGlobal = false;
  return isLoggedIn;
});

  • I am also slightly confused, because i also list the 'TodoFactory' twice. When I take the first reference out 'TodoFactory', just before i pass it in as a function I get a undefined error.

Any help would be greatly appreciated.


Solution

  • Rather than having a property in the service, I would have a getter and a setter:

    todoApp.service('loginService', function() {
        var _loggedIn;
    
        this.setLoggedIn = function (val) {
            _loggedIn = val;
        };
    
        this.isLoggedIn = function () {
            return _loggedIn;
        };
    });
    

    In your controllers, rather than using scope variables, you then call loginService.isLoggedIn() to check if someone is logged in and loginService.setLoggedIn(true) to set them as logged in.

    In your current code, $scope.isLoggedInGlobal in your controllers is not a reference to TodoFactory.isLoggedInGlobal. When you assign to the scope variable the value is copied. So you must update both. They are entirely separate.