HelloWorld
HelloWorld

Reputation: 11249

Why is the Angular Digest Cycle not being called?

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

Answers (2)

Estus Flask
Estus Flask

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:

$watchCollection profiler timeline

While deep $watch profiler timeline will look like this:

deep $watch profiler timeline

Upvotes: 2

shaunhusain
shaunhusain

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

Related Questions