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

}]);
2
  • 2
    You might try using ng-change="updateProgress()" instead of ng-click="updateProgress()". Commented Jun 16, 2014 at 0:56
  • For anyone else coming to this thread, here's another post with other explanations for the same idea: stackoverflow.com/questions/20290738/… Commented Jun 16, 2014 at 2:29

1 Answer 1

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.

Sign up to request clarification or add additional context in comments.

1 Comment

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.