JSFiddle - React, Tailwind, and code Playground

by DotDotDot

HTML

<link rel="stylesheet" href="//netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/css/bootstrap-combined.min.css">
<div data-ng-app="cmdApp">
<div data-ng-controller="UserController">
    
<div class="btn-group pull-right mrr5" data-ng-show="masterChecked">

    <button class="btn btn-danger"><i class="icon-trash"></i> Remove selected</button>
    <button class="btn btn-info"><i class="icon-download icon-white"></i> Export selected as .csv</button>
    
</div>

<table class="table table-hover table-bordered table-list table-striped">


    <thead>
        <tr>
            <td class="span1">
                <three-state-checkbox checkboxes="users" class="select-all-cb" master-checked="masterChecked"></three-state-checkbox>
            </td>
            <th class="span1">
                &nbsp;
            </th>
            <th>Full name</th>
            <th class="span1 text-right">Email</th>
        </tr>
    </thead>
    
    
    <tbody>
        <tr data-ng-repeat="user in users">
            <td>
                <input type="checkbox" id="remove-{{ user.id }}" data-ng-model="user.isSelected" data-ng-change="cbChange()" />
            </td>
            <td>
                <button class="btn btn-small btn-success visible-desktop"><i class="icon-pencil icon-white"></i> Edit</button>
                <button class="btn btn-small btn-success visible-tablet visible-phone"><i class="icon-pencil icon-white"></i></button>
            </td>
            <td>{{ user.firstName }} {{ user.lastName }}</td>
            <td>{{ user.email }}</td>
        </tr>
    </tbody>
</table>
        
</div>
</div>

JavaScript

var cmdApp = angular.module('cmdApp', []);

cmdApp.directive('threeStateCheckbox', function() {
    return {
        replace: true,
        restrict: 'E',
        scope: { checkboxes: '=', masterChecked:"=" },
        template: '<input type="checkbox" data-ng-model="master" data-ng-change="masterChange()">',
        controller: function($scope, $element) {
            //$scope.masterChecked = false;
            $scope.masterChange = function() {
                if ($scope.master) {
                    $scope.masterChecked = true;
                    angular.forEach($scope.checkboxes, function(cb, index){
                        cb.isSelected = true;
                    });
                } else {
                    $scope.masterChecked = false;
                    angular.forEach($scope.checkboxes, function(cb, index){
                        cb.isSelected = false;
                    });
                }
            };
            $scope.$watch('checkboxes', function() {
                var allSet = true;
                var allClear = true;
                angular.forEach($scope.checkboxes, function(cb, index){
                    if(cb.isSelected) {
                        allClear = false;
                    } else {
                        allSet = false;
                    }
                });
                if (allSet) {
                    $scope.masterChecked = true;
                    $scope.master = true;
                    $element.prop('indeterminate', false);
                } else if(allClear) {
                    $scope.masterChecked = false;
                    $scope.master = false;
                    $element.prop('indeterminate', false);
                } else {
                    $scope.masterChecked = true;
                    $scope.master = false;
                    $element.prop('indeterminate', true);
                }
            }, true);
        }
    };
});

cmdApp.controller('UserController', function($scope) {
   ...