AngularJS : Service variable changes not applying
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 recommendations(comments), 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.
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
链接地址: http://www.djcxy.com/p/77540.html上一篇: 在控制器中更改$ scope变量值不会更改视图上的值
下一篇: AngularJS:服务变量更改不适用