Reputation: 183
New to angularJS here. I was originally doing a simple proof-of-concept for myself but then got stuck where I didn't think I would get stuck.
Basically, I have a list of objectives. They are laid out so that each one corresponds to a checkbox bound by the complete
property on the model. If the user checks off one of the objectives, I would like to update the total progress by iterating over the objectives and finding the ones that have been completed (checked).
Each checkbox fires off an event to do this:
<ul>
<li ng-repeat="objective in objectives">
<input type="checkbox" ng-model="objective.complete" ng-click="updateProgress()">
{{ objective.task }}
</li>
</ul>
The problem I am having is that the action is being performed before the model is updated. I suspect this is related to the digest cycle, but since I am new to angular, I couldn't pinpoint exactly how it is related.
Is there a way to accomplish what I am trying to do easily? I feel as if this is not a complicated thing to do, but I am stuck. I had a couple ideas as to what would work including watching the objectives array or checking the ui (which isn't very good design) but haven't had luck yet.
Here is the simplified controller code:
var app = angular.module('checksApp', []);
app.controller('ObjectivesController', ['$scope',
function ($scope) {
$scope.objectives = [];
$scope.objective = { complete: false };
$scope.progress = 0;
$scope.addObjective = function(objective) {
$scope.objectives.push(objective);
$scope.objective = { complete: false };
};
$scope.updateProgress = function() {
if (!$scope.objectives.length) return;
var completed = 0;
angular.forEach($scope.objectives, function(objective) {
if (objective.complete) {
completed++;
}
});
$scope.progress = completed * 100 / $scope.objectives.length;
};
}]);
Upvotes: 1
Views: 133
Reputation: 52847
A couple of ways you can do this. ng-change as Sunil suggested:
<li ng-repeat="objective in objectives">
<input type="checkbox" ng-change="updateProgress()" ng-model="objective.complete" >
{{ objective.task }}
</li>
Or add a deep watch on objectives:
$scope.$watch('objectives', function(newVal) {
$scope.updateProgress();
}, true);
I think using ng-change is easier and less expensive.
Upvotes: 2