JSFiddle - React, Tailwind, and code Playground

by Alien_time

HTML

<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css">
<script src="http://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/0.11.0/ui-bootstrap.min.js"></script>
<div ng-app="angularjs-starter">
    <div ng-controller="MainCtrl">
        <form name="optionForm">
            <checkbox-group min-required="2">Please check at least two options:
                <br />
                <label>Option 1</label>
                <input type="checkbox" ng-model="options.option1" name="option1">
                <label>Option 2</label>
                <input type="checkbox" ng-model="options.option2" name="option2">
                <label>Option 3</label>
                <input type="checkbox" ng-model="options.option3" name="option3">
                <label>Option 4</label>
                <input type="checkbox" ng-model="options.option4" name="option4">
                <label>Option 5</label>
                <input type="checkbox" ng-model="options.option5" name="option5">
            </checkbox-group>
        </form> <pre>{{options}}</pre>
 <pre>Form is valid: {{optionForm.$valid}}</pre>

    </div>
</div>

CSS

.ng-invalid {
    outline: red solid 3px;
    padding: 5px;
}

JavaScript

var app = angular.module('angularjs-starter', ['ui.bootstrap']);

app.controller('MainCtrl', function ($scope) {
    $scope.options = {};
});

app.directive('checkboxGroup', function () {
    return {
        restrict: 'E',
        controller: function ($scope, $attrs) {
            var self = this;
            var ngModels = [];
            var minRequired;
            self.validate = function () {
                var checkedCount = 0;
                angular.forEach(ngModels, function (ngModel) {
                    if (ngModel.$modelValue) {
                        checkedCount++;
                    }
                });
                console.log('minRequired', minRequired);
                console.log('checkedCount', checkedCount);
                var minRequiredValidity = checkedCount >= minRequired;
                angular.forEach(ngModels, function (ngModel) {
                    ngModel.$setValidity('checkboxGroup-minRequired', minRequiredValidity, self);
                });
            };

            self.register = function (ngModel) {
                ngModels.push(ngModel);
            };

            self.deregister = function (ngModel) {
                var index = this.ngModels.indexOf(ngModel);
                if (index != -1) {
                    this.ngModels.splice(index, 1);
                }
            };

            $scope.$watch($attrs.minRequired, function (value) {
                minRequired = parseInt(value, 10);
                self.validate();
            });
        }
    };
});

app.directive('input', function () {
    return {
        restrict: 'E',
        require: ['?^checkboxGroup', '?ngModel'],
        link: function (scope, element, attrs, controllers) {
            var checkboxGroup = controllers[0];
            var ngModel = controllers[1];
            if (attrs.type == 'checkbox' && checkboxGroup && ngModel) {
                checkboxGroup.register(ngModel);
                scope.$watch(function () {
                 ...