Reputation: 2475
I'm currently trying to bind a value to a scope and then watch it, but it doesn't seem to be working correctly. The $watch is never fired. Service.info object and isn't apart of the scope or anything. The service is also the one causing the changes to info and not the Controller with the $watch. Might that causing the issue?
// Service code
function() {
var info = {
prop: false
};
window.addEventListener('offline', function() {
info.prop = !info.prop;
}, false);
return {
info: info
};
}
// Controller code
$scope.info = Service.info;
$scope.$watchCollection('info', function(newValue) {
if (newValue.prop) {
doSomething();
}
});
Upvotes: 1
Views: 2058
Reputation: 2475
So I figured it out. Turns out that the Controller I was calling this in was nested in an ng-if
. Therefore, if the ng-if
equated to false and didn't render the DOM element that the Controller was associated with, the $scope
I was watching on didn't actually exist.
Upvotes: 1
Reputation: 3254
The $watchCollection
is only a shallow watch. So watching info
will only look for changes in info
's properties. If no properties are added or changed, then the watch will not be triggered. To fix this you would need to watch info.prop
or you could use a $watch
and set the flag to use a deep watch - however this will be less performant.
Shallow watches the properties of an object and fires whenever any of the properties change (for arrays, this implies watching the array items; for object maps, this implies watching the properties). If a change is detected, the listener callback is fired.
In this demo you can see that by manipulating info
, the $watchCollection
on info
is triggered. Manipulating prop
, the $watchCollection
on info.prop
is triggered.
<div ng-app ng-controller="ctrl">
<pre>
{{ info | json }}
</pre>
<button ng-click="change()">
Change!
</button>
<button ng-click="addProp()">
Affect info!
</button>
</div>
function ctrl($scope) {
$scope.info = {
prop: {}
};
$scope.change = function() {
$scope.info.prop["dog" + Math.random()] = Math.random();
}
$scope.addProp = function() {
$scope.info["cat" + Math.random()] = Math.random();
}
$scope.$watchCollection('info.prop', function(value) {
if (value) {
console.log("info.prop has changed!");
}
});
$scope.$watchCollection('info', function(value) {
if (value.prop) {
console.log("info has changed!");
}
});
$scope.$watch('info', function(value) {
if (value) {
console.log("deep watch triggered");
}
}, true);
};
Upvotes: 5