這個指令能夠改變一組checkbox的model格式,提交的時候格式爲[x,y,z,...]html
1 var dyDir = angular.module("dyDir", ['']) 15 //複選框指令 16 .directive('checklistModel', ['$parse', '$compile', function ($parse, $compile) { 17 // contains 18 function contains(arr, item, comparator) { 19 if (angular.isArray(arr)) { 20 for (var i = arr.length; i--;) { 21 if (comparator(arr[i], item)) { 22 return true; 23 } 24 } 25 } 26 return false; 27 } 28 29 // add 30 function add(arr, item, comparator) { 31 arr = angular.isArray(arr) ? arr : []; 32 if (!contains(arr, item, comparator)) { 33 arr.push(item); 34 } 35 return arr; 36 } 37 38 // remove 39 function remove(arr, item, comparator) { 40 if (angular.isArray(arr)) { 41 for (var i = arr.length; i--;) { 42 if (comparator(arr[i], item)) { 43 arr.splice(i, 1); 44 break; 45 } 46 } 47 } 48 return arr; 49 } 50 51 // http://stackoverflow.com/a/19228302/1458162 52 function postLinkFn(scope, elem, attrs) { 53 // exclude recursion, but still keep the model 54 var checklistModel = attrs.checklistModel; 55 attrs.$set("checklistModel", null); 56 // compile with `ng-model` pointing to `checked` 57 $compile(elem)(scope); 58 attrs.$set("checklistModel", checklistModel); 59 60 // getter / setter for original model 61 var getter = $parse(checklistModel); 62 var setter = getter.assign; 63 var checklistChange = $parse(attrs.checklistChange); 64 var checklistBeforeChange = $parse(attrs.checklistBeforeChange); 65 66 // value added to list 67 var value = attrs.checklistValue ? $parse(attrs.checklistValue)(scope.$parent) : attrs.value; 68 69 70 var comparator = angular.equals; 71 72 if (attrs.hasOwnProperty('checklistComparator')) { 73 if (attrs.checklistComparator[0] == '.') { 74 var comparatorExpression = attrs.checklistComparator.substring(1); 75 comparator = function (a, b) { 76 return a[comparatorExpression] === b[comparatorExpression]; 77 }; 78 79 } else { 80 comparator = $parse(attrs.checklistComparator)(scope.$parent); 81 } 82 } 83 84 // watch UI checked change 85 scope.$watch(attrs.ngModel, function (newValue, oldValue) { 86 if (newValue === oldValue) { 87 return; 88 } 89 90 if (checklistBeforeChange && (checklistBeforeChange(scope) === false)) { 91 scope[attrs.ngModel] = contains(getter(scope.$parent), value, comparator); 92 return; 93 } 94 95 setValueInChecklistModel(value, newValue); 96 97 if (checklistChange) { 98 checklistChange(scope); 99 } 100 }); 101 102 function setValueInChecklistModel(value, checked) { 103 var current = getter(scope.$parent); 104 if (angular.isFunction(setter)) { 105 if (checked === true) { 106 setter(scope.$parent, add(current, value, comparator)); 107 } else { 108 setter(scope.$parent, remove(current, value, comparator)); 109 } 110 } 111 112 } 113 114 // declare one function to be used for both $watch functions 115 function setChecked(newArr, oldArr) { 116 if (checklistBeforeChange && (checklistBeforeChange(scope) === false)) { 117 setValueInChecklistModel(value, scope[attrs.ngModel]); 118 return; 119 } 120 scope[attrs.ngModel] = contains(newArr, value, comparator); 121 } 122 123 // watch original model change 124 // use the faster $watchCollection method if it's available 125 if (angular.isFunction(scope.$parent.$watchCollection)) { 126 scope.$parent.$watchCollection(checklistModel, setChecked); 127 } else { 128 scope.$parent.$watch(checklistModel, setChecked, true); 129 } 130 } 131 132 return { 133 restrict: 'A', 134 priority: 1000, 135 terminal: true, 136 scope: true, 137 compile: function (tElement, tAttrs) { 138 if ((tElement[0].tagName !== 'INPUT' || tAttrs.type !== 'checkbox') && (tElement[0].tagName !== 'MD-CHECKBOX') && (!tAttrs.btnCheckbox)) { 139 throw 'checklist-model should be applied to `input[type="checkbox"]` or `md-checkbox`.'; 140 } 141 142 if (!tAttrs.checklistValue && !tAttrs.value) { 143 throw 'You should provide `value` or `checklist-value`.'; 144 } 145 146 // by default ngModel is 'checked', so we set it if not specified 147 if (!tAttrs.ngModel) { 148 // local scope var storing individual checkbox model 149 tAttrs.$set("ngModel", "checked"); 150 } 151 152 return postLinkFn; 153 } 154 }; 155 }])
在html頁面上使用方法以下:app
1 <label><input type="checkbox" name="name" checklist-model="checkbox" checklist-value="1"></label> 2 <label><input type="checkbox" name="name" checklist-model="checkbox" checklist-value="2"></label> 3 <label><input type="checkbox" name="name" checklist-model="checkbox" checklist-value="3"></label>
這樣的話,提交時,若是全選中,checkbox的model值爲[1,2,3],是否是方便多了。ide