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 () {
...