javascript - AngularJS : Service variable changes not applying - Stack Overflow

Im currently having an issue where when I call a function in a service that changes its own internal va

Im currently having an issue where when I call a function in a service that changes its own internal variable it doesn't appear to stay unless I change it from a controller. When I output the variable to the console right after I change it, it appears with the correct value. However when I call a function in the controller that prints the object to console it shows the original value.

The variable Im having issues with is "isSignedIn" which always shows false (confirmed with the $scope.verify method in login controller) even after the line "console.log('Signin:' + isSignedIn);" shows true.

Thanks ahead of time for any guidance!

Service Skype

angular.module('Skype', ['ng'])
    .service('skypeClient', function () {
        //Service Properties
        var client = new Skype.Web.Model.Application;
        this.errors = [];
        this.errorCount = -1;
        var isSignedIn = false;
        var state = 'SignedOut';

        var init = function () { 
            client.signInManager.state.when('SignedIn', function () {
                isSignedIn = true;
                console.log('Signin:' + isSignedIn); // This outputs the correct value
            });
            property = client.signInManager.state;
            property.changed(function (status) { 
            state = status;
           console.log("New State"+status) });
           }

        //Signin Function
        var signIn = function (username,password) {
            client.signInManager.signIn({
                username: username,
                password: password
            }).then(function () {
               isSignedIn = true;
                this.errorCount++;
                console.log(this.errorCount);
            });
        }

        //SignOut Function
        var signOut = function () {
        client.signInManager.signOut()
        .then(function () {
           this.isSignedIn = false;
        }, function (error) {
            this.erros.push(error);
            this.errorCount++;
        });
        }

        return {
            signIn: signIn,
            signOut: signOut,
            init: init,
            state: state,
            isSignedIn: isSignedIn
        };

});

Controller Login

'use strict';
angular.module('login', ['ngRoute', 'classy', 'Metio.Skype'])
.config(['$routeProvider', function ($routeProvider) {
    $routeProvider.when('/login', {
        templateUrl: 'app/views/login.html',
        controller: 'loginCntrl'
    });
}]).controller('loginCntrl', function ($scope,skypeClient) {

    skypeClient.init();

    $scope.skypeClient = skypeClient;
    console.log('LoginCntrl Loaded');

    $scope.signIn = function () {
        skypeClient.signIn($scope.user, $scope.password);
    }
    $scope.signOut = function () {
        skypeClient.signOut();
    }
    $scope.verify = function () {
        console.log(skypeClient);
    }
});

[EDIT] Modified Code according to pdenes remendations(ments), same issue but cleaner

Factory Skype

.factory('skypeClient', function () {
        //Service Properties
        var client = new Skype.Web.Model.Application;
        var state = 'SignedOut';
        //Initialize Listeners
        var init = function () {
            client.signInManager.state.when('SignedIn', function () {
                console.log('Signin:' + state); // This outputs the correct value
            });
            property = client.signInManager.state;
            property.changed(function (status) {
                state = status;
                console.log("New State" + state);
            });
            console.log('init');
           }
        //Signin Function
        var signIn = function (username, password) {
           client.signInManager.signIn({
                username: username,
                password: password
            }).then(function () {console.log('LoggedIn');});
        }
        init();
        return {
            signIn: signIn,
            state: function(){return state}
        }
   });

Controller Login

.controller('loginCntrl', function ($scope,skypeClient) {
    $scope.skypeClient = skypeClient;
    $scope.signIn = function () {
        skypeClient.signIn($scope.user, $scope.password);
    }
    $scope.verify = function () {
        console.log(skypeClient);
        console.log($scope.skypeClient);
    }
});

DOM Markup

<input type="checkbox">Keep Me Signed In (Currently Signedin: {{skypeClient.state()}} )

Console Output and DOM Changes

When I hit the signin function the console logs "New State SigningIn" and the dom changes to "Currently Signedin: SigningIn" but when I get the next event fired the console logs "New State SignedIn" but the DOM still reflects the old value "Currently Signedin: SigningIn" so the binding only appears to update the first time but not subsequent times.

Im currently having an issue where when I call a function in a service that changes its own internal variable it doesn't appear to stay unless I change it from a controller. When I output the variable to the console right after I change it, it appears with the correct value. However when I call a function in the controller that prints the object to console it shows the original value.

The variable Im having issues with is "isSignedIn" which always shows false (confirmed with the $scope.verify method in login controller) even after the line "console.log('Signin:' + isSignedIn);" shows true.

Thanks ahead of time for any guidance!

Service Skype

angular.module('Skype', ['ng'])
    .service('skypeClient', function () {
        //Service Properties
        var client = new Skype.Web.Model.Application;
        this.errors = [];
        this.errorCount = -1;
        var isSignedIn = false;
        var state = 'SignedOut';

        var init = function () { 
            client.signInManager.state.when('SignedIn', function () {
                isSignedIn = true;
                console.log('Signin:' + isSignedIn); // This outputs the correct value
            });
            property = client.signInManager.state;
            property.changed(function (status) { 
            state = status;
           console.log("New State"+status) });
           }

        //Signin Function
        var signIn = function (username,password) {
            client.signInManager.signIn({
                username: username,
                password: password
            }).then(function () {
               isSignedIn = true;
                this.errorCount++;
                console.log(this.errorCount);
            });
        }

        //SignOut Function
        var signOut = function () {
        client.signInManager.signOut()
        .then(function () {
           this.isSignedIn = false;
        }, function (error) {
            this.erros.push(error);
            this.errorCount++;
        });
        }

        return {
            signIn: signIn,
            signOut: signOut,
            init: init,
            state: state,
            isSignedIn: isSignedIn
        };

});

Controller Login

'use strict';
angular.module('login', ['ngRoute', 'classy', 'Metio.Skype'])
.config(['$routeProvider', function ($routeProvider) {
    $routeProvider.when('/login', {
        templateUrl: 'app/views/login.html',
        controller: 'loginCntrl'
    });
}]).controller('loginCntrl', function ($scope,skypeClient) {

    skypeClient.init();

    $scope.skypeClient = skypeClient;
    console.log('LoginCntrl Loaded');

    $scope.signIn = function () {
        skypeClient.signIn($scope.user, $scope.password);
    }
    $scope.signOut = function () {
        skypeClient.signOut();
    }
    $scope.verify = function () {
        console.log(skypeClient);
    }
});

[EDIT] Modified Code according to pdenes remendations(ments), same issue but cleaner

Factory Skype

.factory('skypeClient', function () {
        //Service Properties
        var client = new Skype.Web.Model.Application;
        var state = 'SignedOut';
        //Initialize Listeners
        var init = function () {
            client.signInManager.state.when('SignedIn', function () {
                console.log('Signin:' + state); // This outputs the correct value
            });
            property = client.signInManager.state;
            property.changed(function (status) {
                state = status;
                console.log("New State" + state);
            });
            console.log('init');
           }
        //Signin Function
        var signIn = function (username, password) {
           client.signInManager.signIn({
                username: username,
                password: password
            }).then(function () {console.log('LoggedIn');});
        }
        init();
        return {
            signIn: signIn,
            state: function(){return state}
        }
   });

Controller Login

.controller('loginCntrl', function ($scope,skypeClient) {
    $scope.skypeClient = skypeClient;
    $scope.signIn = function () {
        skypeClient.signIn($scope.user, $scope.password);
    }
    $scope.verify = function () {
        console.log(skypeClient);
        console.log($scope.skypeClient);
    }
});

DOM Markup

<input type="checkbox">Keep Me Signed In (Currently Signedin: {{skypeClient.state()}} )

Console Output and DOM Changes

When I hit the signin function the console logs "New State SigningIn" and the dom changes to "Currently Signedin: SigningIn" but when I get the next event fired the console logs "New State SignedIn" but the DOM still reflects the old value "Currently Signedin: SigningIn" so the binding only appears to update the first time but not subsequent times.

Share Improve this question edited Sep 29, 2015 at 11:44 John Slegers 47.2k23 gold badges204 silver badges173 bronze badges asked Aug 15, 2015 at 20:08 strsplstrspl 632 silver badges6 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 7

The value in the object that you return as the service is not the same as the isSignedIn variable you defined earlier. So:

...
var isSignedIn = false;
...
return {
   isSignedIn: isSignedIn  
   //          ^this is false when the object is created
   //           and will remain false, no matter how you
   //           change the value of the above variable later
};

To expose the value of isSignedIn in your closure from the service, you'd need a function, something like:

...
return {
  ...
  isSignedIn: function () { 
    return isSignedIn; // <- this refers to the above variable itself 
  }
};

EDIT: Follow up for the updated code in the question...

So apparently the value is updated properly internally, but the {{skypeClient.state()}} binding is still not updated (only when some other action somehow "forces" it). This is probably happening because the value is updated by something outside of Angular's digest cycle, so there is nothing telling Angular to update things at the right moment.

Looking at the code, state is assigned a new value inside a callback for property.changed (btw, property should properly be declared with var!). Try wrapping that line in an $apply() to make Angular update the bindings!

In place where you call service (factory) value that is returned by function add a $watch. That will update value if it changes in the service.

$scope.$watch(function() { return ModalService.getInfo(); }, function(){
    $scope.info = ModalService.getInfo();
}); 

See solution

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745143989a4613561.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信