Angular.js watch only on particular object property Angular.js watch only on particular object property angularjs angularjs

Angular.js watch only on particular object property


I would not do a watch as depending on how large your array could be, might be very taxing. Instead I would just create a filter:

HTML:

Sum of something is: {{ stuff | sum:'something' }}<br/>Sum of somethingelse is: {{ stuff | sum:'somethingelse' }}

Javascript:

.filter("sum", function(){    return function(input, params){        var totalSum = 0;        for(var x = 0; x < input.length; x++){            totalSum += input[x][params];        }        return totalSum;    }})

plnkr: http://plnkr.co/edit/p6kM3ampSuMXnwqcteYd?p=preview


I am smiling all over the place after I came up with this solution for your problem. Not only is this solution going to watch individual objects, it also is not going to do a complete loop through the rest of the objects for the summation.

http://plnkr.co/edit/oPWobcLLtJlxs5vjTYyc?p=preview

app.controller('MainCtrl', function($scope) {  $scope.stuff = STUFF;  var i;  $scope.sumOfSomething = 0;  $scope.sumOfSomethingElse = 0;  for(i=0;i < $scope.stuff.length;i++ ){    $scope.$watch('stuff['+i+'].something', function (newVal,oldVal) {      // happens when the watch is registered.      if(oldVal === newVal){        $scope.sumOfSomething += +newVal;        return;      }      if(newVal){        $scope.sumOfSomething += + (newVal - oldVal);      }    });    $scope.$watch('stuff['+i+'].somethingelse', function (newVal,oldVal) {      // happens when the watch is registered.       if(oldVal === newVal){        $scope.sumOfSomethingElse += +newVal;        return;      }      if(newVal){        $scope.sumOfSomethingElse += + (newVal - oldVal);      }    });    }});

By the way I dont know how optimal this solution is going to be if you have a large number of objects in STUFF. Also, this wont work as is if the number of objects in STUFF is going to change. What we are basically doing is using the dirty checking loop of angular to do our summation for us.

Also notice the order of newVal and oldVal in the watch listener. Your order is wrong.


Since $watch() takes an angular expression you can use a custom watcher function. In your case the easiest way to watch for changes is simply to add up all the fields you're interested in then return a single number which is nice and efficient for angular and your sum will be ready to render.

var sumThings = function(obj, field) {  var val = 0;  obj.forEach(function(o) {    val += parseInt(o[field]);  });  return val;};$scope.$watch(function() { return sumThings($scope.stuff, "something")}, function (newVal, oldVal) {    //console.log("watchExpression('something') fired!", oldVal, newVal);  $scope.somethingSum = newVal;});$scope.$watch(function() { return sumThings($scope.stuff, "somethingelse")}, function (newVal, oldVal) {  $scope.somethingelseSum = newVal;});

Basically, by doing your summation you're doing your own dirty checking. It'll be more efficient than $watch(STUFF, true) if your objects are more complex than you've shown here.

Your updated plnkr : http://plnkr.co/edit/d7CvERu3XGkub4l6f1yw?p=preview