Recently I had to do an interface at work where there were a list of items, each with a separate checkbox, and a separate “all” checkbox which would check or uncheck all of them. At first that doesn’t seem very complicated but it’s an easy interface to mess up because you want the “all” to become checked if the user manually selects every child checkbox. Or conversely, if “all” is checked then you want it to automatically uncheck if even one child is unchecked.
My page had three separate sections with different lists and an all checkbox for each one. I had done my original design with an extra $scope variable representing the “all” checkbox and used a watch, but it still managed to mess up in certain circumstances. It was overly complicated and didn’t work 100% of the time. So my colleague challenged me to build it without the extra $scope variable because he was certain that was the key to getting a flawless solution. Now that I’ve done it, I agree completely.
Here’s a Plnkr with a running copy of the code so you can play with it: http://plnkr.co/IQA9kq
But I just wanted to point out that what makes this work is really this line here. Instead of having the “all” checkbox reflect some variable via ng-model binding, I’ve just hooked it to two functions which handle the action it should perform (no more watch) and another which governs when it does and doesn’t appear checked.
<input type="checkbox" ng-click="allNeedsClicked()" ng-checked="allNeedsMet()" />All needs
In the next day or two I’m going to add this one to my AngularJS example page but I figured if I wrote about it now I would be more likely to get it done.