Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I get angular.js checkboxes with select/unselect all functionality and indeterminate values?

I am looking for something exactly like these (tri-state checkboxes with "parents"). But using that solution wouldn't be elegant, as I do not depend on jQuery right now, and I would need to call $scope.$apply to get the model to recognize the automatically (un)checked checkboxed jQuery clicked.

Here's a bug for angular.js that requests ng-indeterminate-value implemented. But that still wouldn't give me the synchronization to all the children, which is something I don't think should be a part of my controller.

What I am looking for would be something like this:

  • A "ng-children-model" directive with syntax like: <input type="checkbox" ng-children-model="child.isSelected for child in listelements">. The list of booleans would be computed, and if 0 selected -> checkbox false. If all selected -> checkbox true. Else -> checkbox indeterminate.
  • In my controller, I would have something like this: $scope.listelements = [{isSelected: true, desc: "Donkey"},{isSelected: false, desc: "Horse"}]
  • The checkboxes would be made as usual with <tr ng-repeat="elem in listelements"><td><input type="checkbox" ng-model="elem.isSelected"></td><td>{{elem.desc}}</td></tr>.
  • As I understand it, the browser will determine which state a clicked indeterminate checkbox goes into.
like image 906
Janus Troelsen Avatar asked Sep 28 '12 23:09

Janus Troelsen


People also ask

How do you select or deselect all checkboxes using JavaScript?

Code Explanation For the input types as button, we have created one button for selecting the checkboxes where onClick (), the selects () function will be invoked and the other one for deselecting the checkboxes (if selected any/all) where onClick () the deselect () function will be invoked.

How do I set an indeterminate checkbox?

Checkboxes actually has three states: true, false and indeterminate which indicates that a checkbox is neither "on" or "off". A checkbox cannot be set to indeterminate state by an HTML attribute - it must be set by a JavaScript. This state can be used to force the user to check or uncheck the checkbox.

What happens when you click an indeterminate checkbox?

Note: If you submit a form with an indeterminate checkbox, the same thing happens as if the checkbox were unchecked — no data is submitted to represent the checkbox.


1 Answers

Since you want a new type/kind of component, this sounds like a good case for a custom directive.
Since the parent/master/tri-stated checkbox and the individual dual-state checkboxes need to interact with each other, I suggest a single directive, with its own controller, to handle the logic.

<tri-state-checkbox checkboxes="listelements"></tri-state-checkbox> 

Directive:

app.directive('triStateCheckbox', function() {   return {     replace: true,     restrict: 'E',     scope: { checkboxes: '=' },     template: '<div><input type="checkbox" ng-model="master" ng-change="masterChange()">'       + '<div ng-repeat="cb in checkboxes">'       + '<input type="checkbox" ng-model="cb.isSelected" ng-change="cbChange()">{{cb.desc}}'       + '</div>'       + '</div>',     controller: function($scope, $element) {       $scope.masterChange = function() {         if($scope.master) {           angular.forEach($scope.checkboxes, function(cb, index){             cb.isSelected = true;           });         } else {           angular.forEach($scope.checkboxes, function(cb, index){             cb.isSelected = false;           });         }       };       var masterCb = $element.children()[0];       $scope.cbChange = function() {         var allSet = true, allClear = true;         angular.forEach($scope.checkboxes, function(cb, index){           if(cb.isSelected) {             allClear = false;           } else {             allSet = false;           }         });         if(allSet)        {            $scope.master = true;            masterCb.indeterminate = false;         }         else if(allClear) {            $scope.master = false;            masterCb.indeterminate = false;         }         else {            $scope.master = false;           masterCb.indeterminate = true;         }       };       $scope.cbChange();  // initialize     },   }; }); 

Change the template to suit your needs, or use an external template with templateUrl.

The directive assumes that the checkboxes array contains objects that have an isSelected property and a desc property.

Plunker.

Update: If you prefer to have the directive only render the tri-stated checkbox, hence the individual checkboxes are in the HTML (like @Piran's solution), here's another plunker variation for that. For this plunker, the HTML would be:

<tri-state-checkbox checkboxes="listelements" class="select-all-cb"> </tri-state-checkbox>select all <div ng-repeat="item in listelements">    <input type="checkbox" ng-model="item.isSelected"> {{item.desc}} </div> 
like image 70
Mark Rajcok Avatar answered Oct 08 '22 08:10

Mark Rajcok