I have two Controllers and one shared Service. First Controller renders some text. Other Controller has a button that had to change the First Controllers scope and rerender text (with new value)
HTML
<div ng-controller="Controller1">
Value is: {{object}}
</div>
<div ng-controller="Controller2">
<button ng-click="changeValue()">Click to change Value</button>
</div>
JS
function Controller1($scope, mainServices) {
$scope.object = mainServices.getValue();
};
function Controller2($scope, mainServices) {
$scope.changeValue = function(){
mainServices.getValue('Hello');
console.log('button is pressed');
};
};
testApp.factory('mainServices', function(){
return {
getValue: function(update) {
var defaultValue = 'Hi';
if( typeof(update)==='undefined') { value = defaultValue; }
else { value = update; }
console.log('should be changed to', update);
return value;
}
}
});
On Plunker
Why doesn't this work? How to tell Angular to watch for changes?
I have two Controllers and one shared Service. First Controller renders some text. Other Controller has a button that had to change the First Controllers scope and rerender text (with new value)
HTML
<div ng-controller="Controller1">
Value is: {{object}}
</div>
<div ng-controller="Controller2">
<button ng-click="changeValue()">Click to change Value</button>
</div>
JS
function Controller1($scope, mainServices) {
$scope.object = mainServices.getValue();
};
function Controller2($scope, mainServices) {
$scope.changeValue = function(){
mainServices.getValue('Hello');
console.log('button is pressed');
};
};
testApp.factory('mainServices', function(){
return {
getValue: function(update) {
var defaultValue = 'Hi';
if( typeof(update)==='undefined') { value = defaultValue; }
else { value = update; }
console.log('should be changed to', update);
return value;
}
}
});
On Plunker http://plnkr.co/edit/IWBEvAfvLbzJ0UD2IqGB?p=preview
Why doesn't this work? How to tell Angular to watch for changes?
Share Improve this question asked Jun 16, 2013 at 12:48 pakapaka 1,64122 silver badges35 bronze badges 2- But I hope this is just some sample code, it would be easier to have just one controller with this... – DerWaldschrat Commented Jun 16, 2013 at 13:45
- 1 Sure, in real app this controllers in diffirent views – paka Commented Jun 16, 2013 at 14:08
1 Answer
Reset to default 8The code
Well, I think this is not the best solution, but it is possible for your problem. Instead of just changing the value itself, you have to create an object before the return statement in the factory.
var obj = {}
And then you just change a property of this object:
if( typeof(update)==='undefined') { obj.val = defaultValue; }
else { obj.val = update; }
And return the object:
return obj;
The other controller can be left unaffected, however you have to change your html: You have to put in
{{object.val}}
in order to listen to changes.
http://plnkr.co/edit/rjsrkbaQ8QyWGGFI9HYl?p=preview
Why does this work?
It is quite simple: In javascript, if you call a function with a primitive return value like a string (yes, strings CAN be primitives in javascript), it is just a copy of this primitive, so with
$scope.object = mainServices.getValue();
you just pass a value to $scope.object, which is not affected by other calls of getValue() But if we return an object from getValue(), we get a reference to this object. So if we make changes to this referenced object in getValue(), angularjs will be able to notice the changed object because it is tracked in both controllers. Therefore we have to reference the same object again and again, but since javascript supports closures, this is pretty easy.