3 * AngularJS directive for list of checkboxes
6 angular.module('checklist-model', [])
7 .directive('checklistModel', ['$parse', '$compile', function($parse, $compile) {
9 function contains(arr, item) {
10 if (angular.isArray(arr)) {
11 for (var i = 0; i < arr.length; i++) {
12 if (angular.equals(arr[i], item)) {
21 function add(arr, item) {
22 arr = angular.isArray(arr) ? arr : [];
23 for (var i = 0; i < arr.length; i++) {
24 if (angular.equals(arr[i], item)) {
33 function remove(arr, item) {
34 if (angular.isArray(arr)) {
35 for (var i = 0; i < arr.length; i++) {
36 if (angular.equals(arr[i], item)) {
45 // http://stackoverflow.com/a/19228302/1458162
46 function postLinkFn(scope, elem, attrs) {
47 // compile with `ng-model` pointing to `checked`
48 $compile(elem)(scope);
50 // getter / setter for original model
51 var getter = $parse(attrs.checklistModel);
52 var setter = getter.assign;
54 // value added to list
55 var value = $parse(attrs.checklistValue)(scope.$parent);
57 // watch UI checked change
58 scope.$watch('checked', function(newValue, oldValue) {
59 if (newValue === oldValue) {
62 var current = getter(scope.$parent);
63 if (newValue === true) {
64 setter(scope.$parent, add(current, value));
66 setter(scope.$parent, remove(current, value));
70 // watch original model change
71 scope.$parent.$watch(attrs.checklistModel, function(newArr, oldArr) {
72 scope.checked = contains(newArr, value);
81 compile: function(tElement, tAttrs) {
82 if (tElement[0].tagName !== 'INPUT' || tAttrs.type !== 'checkbox') {
83 throw 'checklist-model should be applied to `input[type="checkbox"]`.';
86 if (!tAttrs.checklistValue) {
87 throw 'You should provide `checklist-value`.';
91 tElement.removeAttr('checklist-model');
93 // local scope var storing individual checkbox model
94 tElement.attr('ng-model', 'checked');