AngularJS SelectAll Checkbox

by wldaunfr

HTML

<link rel="stylesheet" href="http://current.bootstrapcdn.com/bootstrap-v204/css/bootstrap-combined.min.css">
<script src="http://current.bootstrapcdn.com/bootstrap-v204/js/bootstrap.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.0.4/angular.js"></script>
<div ng:controller="PlaygroundController" class="container">
    <div ng-repeat="elem in list">
        <input type="checkbox" ng-model="elem.isSelected" /> {{elem.desc}}
    </div>
    <hr/>
    <ui-select-all items="list" prop="isSelected"></ui-select-all> Select all
</div>

JavaScript

PlaygroundController.$inject = ['$scope'];
function PlaygroundController($scope) {
    $scope.list = [{desc: 'Item 1'}, {desc: 'Item 2'}, {desc: 'Item 3'}];
};

angular
.module('myApp', [])
.directive('uiSelectAll', ['$filter', function($filter) {
    return {
        restrict: 'E',
        template: '<input type="checkbox">',
        replace: true,
        link: function(scope, iElement, iAttrs) {
            function changeState(checked, indet) {
                iElement.prop('checked', checked).prop('indeterminate', indet);
            }
            function updateItems() {
                angular.forEach(scope.$eval(iAttrs.items), function(el) {
                    el[iAttrs.prop] = iElement.prop('checked');
                });
            }
            iElement.bind('change', function() {
                scope.$apply(function() { updateItems(); });
            });
            scope.$watch(iAttrs.items, function(newValue) {
                var checkedItems = $filter('filter')(newValue, function(el) {
                    return el[iAttrs.prop];
                });
                switch(checkedItems ? checkedItems.length : 0) {
                    case 0:                // none selected
                        changeState(false, false);
                        break;
                    case newValue.length:  // all selected
                        changeState(true, false);
                        break;
                    default:               // some selected
                        changeState(false, true);
                }
            }, true);
            updateItems();
        }
    };
}]);