1

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;
    };

}]);
jcomo
  • 183
  • 6
  • 2
    You might try using `ng-change="updateProgress()"` instead of `ng-click="updateProgress()"`. – Sunil D. Jun 16 '14 at 00:56
  • For anyone else coming to this thread, here's another post with other explanations for the same idea: http://stackoverflow.com/questions/20290738/angular-checkbox-and-ng-click – jcomo Jun 16 '14 at 02:29

1 Answers1

2

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.

Michael Kang
  • 52,003
  • 16
  • 103
  • 135
  • I did try $watch but I figured there was an easier way to do it. Didn't know about ng-change. I'll have to take a closer look at the docs. Thanks – jcomo Jun 16 '14 at 02:28