There are a number of approaches you could take, but they all start by caching the count of the number of items that are completed when the controller loads.
You could use the $watch function to monitor the array, and update a counter when the object changes. The following is untested, but should give you a sense of how to do it
function myCtl($scope, itemFetcher) {
$scope.items = itemFetcher.get(); //retrieves your array of items
$scope.numComplete = countComplete();
$scope.$watch("items", function(newValue, oldValue) {
$scope.items = newValue;
$scope.numComplete = countComplete();
}, true); // NOTE: passing true into $watch is necessary to do a deep compare (i.e. comparing object properties), and I think it is required in this case, but it has a negative impact on performance & memory.
function countComplete() {
var cnt = 0;
angular.forEach($scope.items, function(item) {
cnt += item.completed ? 1 : 0;
}
return cnt;
}
}
Alternatively, you can update the completed count in functions that modify the items completed state. The following code is also untested.
function myCtl($scope, itemFetcher) {
$scope.items = itemFetcher.get(); //retrieves your array of items
$scope.numComplete = countComplete();
$scope.markItem = function(index, newState) { // this function is referenced in your HTML template
$scope.items[index].complete = newState;
$scope.numComplete += (newState) ? 1 : -1;
}
function countComplete() {
var cnt = 0;
angular.forEach($scope.items, function(item) {
cnt += item.completed ? 1 : 0;
}
return cnt;
}
}
Using $watch is more convenient and less error-prone, but may cause performance issues depending on the size of the items array. The second approach is more efficient, but tougher to maintain.