Tim Tim - 1 year ago 78
AngularJS Question

AngularJS : watching a particular property in an array of objects for changes in the property's value

In my custom directive, I'm adding elements to the DOM based on the number of objects in my datasource array. I need to watch a specific property in each object. As I add these elements to the DOM, I want to set up a $watch on the

property of each object in the
array, but it's not working, and I don't know why. I set up a breakpoint inside the function that should be invoked when the property changes from true to false or false to true, but that function is never invoked. Is the reason obvious? I'm just learning Angular, so I could easily be making a stupid error.

$scope.bits = 66; (i.e. onions and olives)

$scope.toppings = [
{ topping: 1, bits: 2, name: 'onions' },
{ topping: 2, bits: 4, name: 'mushrooms' },
{ topping: 3, bits: 8, name: 'peppers' },
{ topping: 4, bits: 16, name: 'anchovies' },
{ topping: 5, bits: 32, name: 'artichokes' },
{ topping: 6, bits: 64, name: 'olives' },
{ topping: 7, bits: 128, name: 'sausage' },
{ topping: 8, bits: 256, name: 'pepperoni' }

Each object in the model gets a new
property which will be true or false.

NOTE: the object array will at most contain a dozen or so items. Performance is not a concern.

link: function link(scope, iElement, iAttrs, controller, transcludeFn) {


// At this point scope.model refers to $scope.toppings. Confirmed.

angular.forEach(scope.model, function (value, key) {

// bitwise: set checked to true|false based on scope.bits and topping.bits

scope.model[key].checked = ((value.bits & scope.bits) > 0);

scope.$watch(scope.model[key].checked, function () {
var totlBits = 0;
for (var i = 0; i < scope.model.length; i++) {
if (scope.model[i].checked) totlBits += scope.model[i].bits;
scope.bits = totlBits;



Answer Source

The watchExpression parameter to $scope.$watch should either be a string or a function. I've not experimented extensively with this (I try and avoid explicit watches where possible) but I think it does also work when you watch 'simple' scope properties as object references, but not so well with more complex references.

I think if you supply the reference as a string, e.g. 'model[' + key + '].checked' then you may have some success (I only say this because I've done something similar with $watchCollection previously).

Alternatively you should be able to supply a function, e.g.

$scope.$watch(function() { return scope.model[key].checked; }, function() { ... });

Hope this helps!

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download