0

i am trying to check all checkboxes in angular's way.

I have the following codes:

 <div>
     <div class="checkbox">
          <input ng-click="checkAll =! checkAll" type="checkbox"/> check all
     </div>
     <div class="checkbox" ng-repeat="item in items">
          <input type="checkbox" ng-model="checkAll"/> {{item.title}}
     </div>
</div>

I was able to check all checkboxes when I click the check all, however, if I check and uncheck the individual checkbox, the check all doesn't seem to applied that individual checkbox anymore. Can anyone help me about this issue? Thanks a lot!

FlyingCat
  • 14,036
  • 36
  • 119
  • 198

2 Answers2

3

Revised answer:

An alternative approach to the other answer using a directive:

app.directive('myCheckBox', function(){
  return {
    restrict: 'E',
    scope: {
      checkAll: '=',
    },
    template: '<input check-all="checkAll" type="checkbox" ng-model="check"/>',
    replace: true,
    link: function(scope) {
      scope.$watch('checkAll', function(newVal){
        scope.check = newVal;
      })
    },

  }
})

I passed the parent scope's checkAll to the new directive's scope and added a watcher for it.

plunker


Old answer:

You can use $parent (will access the scope's parent scope):

<input type="checkbox" ng-model="$parent.checkAll"/> {{item.title}}

plunker

And you should have checkAll as ng-model for the main checkbox as well, rather than as a click event.

The problem you were having is due to ngRepeat creating a scope for each repetition.

Mosho
  • 7,099
  • 3
  • 34
  • 51
  • Your demo doesn't work. Every checkbox does the same thing (selects/deselects all checkboxes). Only "check all" should check all the boxes. a, b, and c should work independently. – Jerrad Jul 01 '14 at 01:57
  • @Jerrad thought that's what he wanted, now I see I misread. On it. – Mosho Jul 01 '14 at 02:03
1

You didn't show what your $scope.items looks like. If it is an array of primitives, then that's a problem. ng-repeat will create a new scope for each item that inherits from the parent scope. The problem is that for primitives, it just makes a copy of the value, and you lose the two-way binding. Instead, make your items an array of objects, like this:

$scope.items = [
  {name: 'a', checked: false}, 
  {name: 'b', checked: false}, 
  {name: 'c', checked: false}
];

You should also have a separate variable for the "Check All" checkbox.

$scope.checkAll = false;

Now make a function to loop through all the items and set the checked property:

$scope.checkAllBoxes = function(){
    $scope.checkAll = !$scope.checkAll;
    angular.forEach($scope.items, function(item){
      item.checked = $scope.checkAll;
    })
}

Bind it all up like this:

<div class="checkbox">
      <input type="checkbox" ng-click="checkAllBoxes()" /> check all
</div>
<div class="checkbox" ng-repeat="item in items">
      <input type="checkbox" ng-model="item.checked"/> {{item.name}}
</div>

Demo

Jerrad
  • 5,240
  • 1
  • 18
  • 23