Went a bit nuts today trying to research how Angular could deal with checkboxes from an HTML form.  Everywhere I was reading, it seems that Angular only allows one ng-model per checkbox, but my list was dynamic, meaning the ng-model expression would be the same for every checkbox, and I had many to display in a list.  My bad habits first tuned me to jQuery, but I knew that was not good practice, and well, I wanted to learn everything I could about Angular. So here we go, my solution.

Let’s start with the HTML.  Before we get to the actual checkboxes, I wanted to include the Select All | Unselect All options like this:

<a href="Javascript:;" ng-click="checkAll()">Select All</a> | <a ng-click="uncheckAll()" href="Javascript:;">Deselect All</a>

Ignore the ng-click’s for now, we’ll come to that later as it will just confuse you at this time.  Just know you will need them later and feel free to style them any way you want.

Note: See that neat little trick to prevent default click actions from Angular?  Use the Javascript: ; and your link will not act like a normal link, because including the anchor (#) leads to dead pages in Angular apps.

Now let’s get to the HTML content that displays the list of checkboxes.

<div class="list-group" ng-repeat="obj in objects">
 <input type="checkbox" ng-checked="allChecked" ng-click="handleCheckBox(obj.id)"> {{obj.someProperty}}
</div>

Again, let’s not get bogged down into details about the ng-click action or the ng-checked option.  They come later as well, we are simply setting the stage for HTML content.  Also know you will be iterating thru some kind of list as we show with the ng-repeat directive.  We can first assume that the collection of objects coming back was from something like an asnyc call using $http.

Ok now let’s move into the controller once the template code has been stubbed.  We need to fill in some gaps here and explain what is going on.  First, the list of objects coming back.  It’s simple to think that the objects was a JSON result from $http, but in fact we had to massage the contents a little bit.  Regardless of the structure of your object, we need to include one, maybe 2 values in the object.  So before we just return the data on the $scope back to the view, we want to update the collection first.

// Assume we have the data from either some array or some JSON response
$scope.objects = [];  // Create an empty array that will get passed back to the UI
 angular.forEach(someListOfValuesFromTheServer, function(value, key) {
 $scope.objects.push({ id: key, enabled: false, value: value});
 });

So let’s talk about what is going on here. First, the value: value is just assigning the value of the full object into something called value.  Really this is the original object returned from the server in it’s raw form.  Our JSON response contained the following data after the $http call was made:

someListOfValuesFromTheServer

Great.  And assume our object does not contain an ID (odd I know, perhaps yours will, and that is still ok, stick with me now).  We want to iterate thru the native list of values using the convenient angular.forEach function where we create a new collection of data, that includes an enabled flag as well as an ID, assuming your object does not already contain one.  In our case, we are using the key as the “key” to the list.  However, if your object in the list of someListOfValuesFromTheServer contains an id, you would replace id: key with id: someListOfValuesFromTheServer.id.  We push this new collection called objects on to the scope so we can use it in our view. Whew!

So referring back to our view code that displays the list of checkboxes, this code will make more sense:

<div class="list-group" ng-repeat="obj in objects">
 <input type="checkbox" ng-checked="allChecked" ng-click="handleCheckBox(obj.id)"> {{obj.someProperty}}
</div>

So far so good, but how about those functions we defined in this code?  How do they hook up and work.  Well let’s fill them in now and explain.

Here is a sample of what we use in our controller:

$scope.handleCheckBox = function(id) {
 $scope.objects[id].enabled = !$scope.objects[id].enabled;
 }
$scope.checkAll = function() {
 angular.forEach($scope.objects, function(value, key) {
 value.enabled = true;
 });
 $scope.allChecked = true;
 }
$scope.uncheckAll = function() {
 angular.forEach($scope.objects, function(value, key) {
 value.enabled = false;
 }); 
 $scope.allChecked = false;
 }

To get your started, you can copy/paste these functions directly into your controller and replace the “objects” list with the list you may have used.

handleCheckBox is executed when someone clicks on the checkbox (via ng-click) as we defined earlier.  When it’s clicked, we update the enabled flag for that collection.

checkAll is executed when someone clicks on the Select All link (via ng-click)

uncheckAll is executed when someone clicks on the Deselect All (via ng-click).  Sorry, some inconsistent naming conventions, ah well, it’s all semantics and you can update that if you like 🙂

So in a nutshell, we are simply managing the checkbox with a scoped collection of objects so that when the time comes to working with the objects, we can filter the results based on the Enabled flag.  This allows us to do whatever we wish with the selected values.

As much as this post may seem like a lot is going on, it’s much easier than it looks.  Most of the examples I found were too complex for something that I felt should be easy.