Reputation: 11249
I have two controllers and a factory. I am injecting the factory and a controller into a main controller, here are the code snippets below:
Factory:
app.factory('TallyFactory', function(){
return {
correct: 0,
incorrect: 0
};
});
TallyController that accepts the TallyFactory:
app.controller('TallyController', function($scope, TallyFactory){
$scope.$watch('scores', function(newValue, oldValue){
console.info('changed!');
console.log('Old: ' + JSON.stringify(oldValue));
console.log('New: ' + JSON.stringify(newValue));
});
$scope.scores = TallyFactory;
});
MainController which accepts the TallyFactory and changes the value of the TallyFactory Object:
app.controller('MainController', function ($scope,TallyFactory) {
$scope.addTally = function(){
TallyFactory.correct++;
}
});
Notice in my TallyController (second snippet), I added a watcher to the $scope, listening for when "scores" changes.
When I run the "addTally" function from my MainController with an ng-click, it changes the value of my Factory Object (TallyFactory). Since there was a change, and I specifically created a watcher on my TallyController ($scope.scores), shouldn't the digest cycle be triggered and my console update with the new value of my TallyFactory?
Also, my TallyController is NOT nested in my MainController, they are separate from each other (not 100% sure if that matters).
I'm not sure why the Digest Loop isn't triggered since the TallyFactory changed values.
Upvotes: 0
Views: 334
Reputation: 223054
$scope.$watch('scores.correct', function(newValue, oldValue){ ... });
to watch for particular property. And
$scope.$watchCollection('scores', function(newValue, oldValue){ ... });
to watch for all of them.
Consider using deep $watch
$scope.$watch('scores', function(newValue, oldValue){ ... }, true);
instead if scores
properties may contain objects.
In comparison with deep $watch
, $watchCollection
provides significant performance boost even for simple shallow objects. Here is profiler timeline for $watchCollection:
While deep $watch profiler timeline will look like this:
Upvotes: 2
Reputation: 19748
I had some doubts about the exact correctness of the answer but after copying your code into a snippet that can be run I just verified here that estus' answer is acceptable.
angular.module('app', [])
.controller('TallyController', function($scope, TallyFactory){
$scope.scores = TallyFactory;
$scope.$watch('scores', function(newValue, oldValue){
alert('changed!');
console.log('Old: ' + JSON.stringify(oldValue));
console.log('New: ' + JSON.stringify(newValue));
}, true);
})
.factory('TallyFactory', function(){
return {
correct: 0,
incorrect: 0
};
})
.controller('MainController', function ($scope,TallyFactory) {
$scope.addTally = function(){
TallyFactory.correct++;
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js"></script>
<div ng-app='app'>
<div ng-controller="TallyController">
{{scores}}
</div>
<div ng-controller="MainController">
<button ng-click="addTally()">Add Tally</button>
</div>
</div>
Upvotes: 1