0

Im trying to build a login modal that will update templates (just basic user info - avatars,names,etc..) across different controllers. Loosely following this example, my approach has been to bind service variables directly within my partials like this:

partial:

<div ng-controller="TopBarControl">
    <span>{{ userService.getInfo() }}</span>
</div>

service:

.service('userService', function($http) {

    this.userInfo = {
        isLogged: false         
    }

    this.getInfo = function() {
        return this.userInfo;
    }

    this.loginInit = function(userName, password) {
        $http.get('http://example.com/?json=get_nonce&controller=auth&method=generate_auth_cookie').success(
        function(data, status, headers, config) {
            var nonce = data.nonce;
            $http.get('http://example.com/?json=auth/generate_auth_cookie&nonce='+nonce+'&username='+userName+'&password='+password).success(function(data, status, headers, config) {
                if (data.status == 'ok') {
                    this.userInfo = [
                        {isLogged: true},
                        {username: data.user.username},
                        {firstName: data.user.firstname},
                        {lastName: data.user.lastname},
                        {avatar: data.user.avatar}
                    ];
                    return userInfo;
                } 
               /* handle errors and stuff*/     
        }); 
    }
})

controllers:

.controller('TopBarControl', function($scope, $modal, userService) {

    $scope.userService = userService;

    $scope.openLogin = function() {
        var modalInstance = $modal.open({
        templateUrl: 'views/modal.html',
        controller: ModalInstanceCtrl,
        size: 'lg'
      });
    }   
});

var ModalInstanceCtrl = function ($scope, $modalInstance, userService) {
  $scope.login = function () {
    userService.loginInit(this.userName, this.password);
  };

  $scope.ok = function () {
    $modalInstance.close($scope.returnResolveVariable);
  };
};

So, the login works. Data is sent to the server and the correct data is successfully brought back to the app. The two-way binding sorta works - every time there is a change, the template calls back to .getInfo() and spits out the value of userInfo. The problem is that the value of userInfo never changes. I can't figure out if its something weird about how I am setting the variable in loginInit or if there is something that I fundamentally don't understand about how services handle variables like this.

2
  • In your example, where is the relation between the controller's userInfo and the service's userInfo variables. They aren't the same variable. Commented Jun 26, 2014 at 16:36
  • Whoops... that was commented - it was just a reference for the array I wanted to produce. I deleted it for clarity. Commented Jun 26, 2014 at 16:45

1 Answer 1

1

It is your use of the 'this' keyword. The context of the 'this' keyword when you set the this.userinfo for the first time is different from the 'this' context in the $http handling methods.

Do something like this which captures the original context of the 'this' keyword so you can use it later:

.service('userService', function($http) {
    var self = this;

    this.userInfo = {
        isLogged: false         
    };

    this.getInfo = function() {
        return this.userInfo;
    };

    this.loginInit = function(userName, password) {
        $http.get('http://example.com/?json=get_nonce&controller=auth&method=generate_auth_cookie').success(
        function(data, status, headers, config) {
            var nonce = data.nonce;
            $http.get('http://example.com/?json=auth/generate_auth_cookie&nonce='+nonce+'&username='+userName+'&password='+password).success(function(data, status, headers, config) {
                if (data.status == 'ok') {
                   self.userInfo = [
                        {isLogged: true},
                        {username: data.user.username},
                        {firstName: data.user.firstname},
                        {lastName: data.user.lastname},
                        {avatar: data.user.avatar}
                    ];
                    return userInfo;
                } 
               /* handle errors and stuff*/     
        }); 
    };
});

In the above code the userInfo variable will be scoped into the inline handler function on the return of the $http call.

Understanding the 'this' keyword is pretty tricky this looks like a good introduction 'http://javascriptissexy.com/understand-javascripts-this-with-clarity-and-master-it/' although I tend not to use it and use the revealing module pattern for my services which gets rid of this confusion see here for an example

Sign up to request clarification or add additional context in comments.

1 Comment

No worries, JavaScript is a tricky thing but you will grow to love it!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.