user1184100
user1184100

Reputation: 6894

$watchCollection not working on array

I'm using $watchCollection to watch for changes in an array length. But it doesn't seem to work when I add any item onto the array. Where am I going wrong ?

var app = angular.module('plunker', []);

app.controller('MainCtrl', function($scope) {

  $scope.count;
  $scope.Items = {
      "Cars" : [
          {
              "id" : 1,
              "name" : "Mercedes"
          },
          {
              "id": 2,
              "name" : "Ferrari"
          }

      ],
      "Bikes" : [
           {
              "id" : 1,
              "name" : "Ducati"
          },
          {
              "id": 2,
              "name" : "Yamaha"
          } 

      ]
  }

  $scope.addCar = function() {
    $scope.Items.Cars.push({
        'id' : 3,
        "name" : "random name"
    })
  }

  $scope.$watchCollection($scope.Items.Cars, function(newNames, oldNames) {
    $scope.count = $scope.Items.Cars.length;
    console.log($scope.count);
  })

});

Demo : http://plnkr.co/edit/dSloJazZgr3mMevIHOe8?p=preview

Upvotes: 4

Views: 5156

Answers (2)

user3338098
user3338098

Reputation: 874

I had a different issue. Consider the following:

app.controller('MainCtrl', function($scope) {
  unwatch = $scope.$watch('variableName', function() {
    [...];
  },true);
  setInterval(function() {
    $scope.variable++;
    $scope.$apply();
  }, 1000);
});

and I had another controller

app.controller('RelatedCtrl', function($scope) {
  unwatch = $scope.$watch('totallyUnrelated', function() {
    [...];
  },true);
});

the problem was that the assignment unwatch = [...]; is the same as window.unwatch = [...];

therefore when the other controller decided to unwatch it was actually unwatching a watcher in a different scope...

The solution

use var unwatch = [...]; to make the variable local to the current function scope (js scope, not angular scope).

e.g.

app.controller('MainCtrl', function($scope) {
  var unwatch = $scope.$watch('variableName', function() {
    [...];
  },true);
  setInterval(function() {
    $scope.variable++;
    $scope.$apply();
  }, 1000);
});

Upvotes: -1

John Ledbetter
John Ledbetter

Reputation: 14173

You should pass an expression as the first variable to $watchCollection, not an object:

$scope.$watchCollection('Items.Cars', function(newNames, oldNames) {
  $scope.count = $scope.Items.Cars.length;
  console.log($scope.count);
})

plnkr example.

Upvotes: 9

Related Questions