0

I need to watch for changes in the list of objects, and perform some action on change, however, Angular $watch is triggered only once, when list was first created and initial object was pushed into it:

$scope.$watch('components', function(newComponents, oldComponents) {
  if (typeof $scope.components !== 'undefined')) {
    return;
  }
  // this alert show only on first change
  alert('change');
});

// only pushing first object triggers the $watch
$scope.components.push({ id: 1, name: 'first component'});
$scope.components.push({ id: 2, name: 'second component'});
$scope.components.push({ id: 3, name: 'third component'});
JasonMArcher
  • 14,195
  • 22
  • 56
  • 52
mikhail-t
  • 4,103
  • 7
  • 36
  • 56

2 Answers2

1

The solution is to use $watchCollection instead of $watch method:

$scope.$watchCollection('components', function(newComponents, oldComponents) {
  if (typeof $scope.components !== 'undefined')) {
    return;
  }
  // now this alert will show for each new element added!
  alert('change');
});

Source: https://code.angularjs.org/1.3.15/docs/api/ng/type/$rootScope.Scope#$watchCollection

mikhail-t
  • 4,103
  • 7
  • 36
  • 56
  • In example you provided $watch is not triggered by push - you can remove all pushed and still get one change. This is because $watch expression is evaluated once per digest cycle - not immediately after u change values. – Petr Averyanov May 08 '15 at 16:06
0

To note, $watchCollection only watches 1 level deep in objects/arrays. This seems fine in your case.

To watch more complex objects, with multiple levels of depth, need to use $watch with "true" as a second attribute.

Check out this for a detailed explanation of $watch vs $watchCollection

Community
  • 1
  • 1
Artem K.
  • 804
  • 6
  • 15