<!doctype html>
<html ng-app="plunker">
<head>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.8/angular.js"></script>
<script src="example.js"></script>
<script src="checklist-model.js"></script>
<link href="//netdna.bootstrapcdn.com/bootstrap/3.0.3/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div ng-controller="DemoCtrl">
<label ng-repeat="role in roles">
<input type="checkbox" checklist-model="user.roles" checklist-value="role"> {{role.text}}
</label>
<button ng-click="user.roles=[];" style="margin-right: 10px">Uncheck all</button>
<button ng-click="checkNth(0)">Check first</button>
<button ng-click="checkAll()">Check all</button>
<pre>{{ user.roles | json }}</pre>
</div>
</body>
</html>
angular.module('plunker', ['checklist-model']);
var DemoCtrl = function ($scope) {
$scope.roles = [
{id: 1, text: 'guest'},
{id: 2, text: 'user'},
{id: 3, text: 'customer'},
{id: 4, text: 'admin'}
];
$scope.user = {
roles: [$scope.roles[1]]
};
$scope.checkAll = function() {
// this first method doesn't work
//$scope.user.roles = $scope.roles;
// this one work
for(i=0;i<$scope.roles.length;i++)
$scope.checkNth(i);
};
$scope.checkNth = function(i) {
console.log("first", JSON.stringify($scope.user.roles));
$scope.user.roles.splice(i, $scope.user.roles.length);
console.log("second", JSON.stringify($scope.user.roles));
$scope.user.roles.push($scope.roles[i])
console.log("third", JSON.stringify($scope.user.roles));
}
};
/**
* Checklist-model
* AngularJS directive for list of checkboxes
*/
angular.module('checklist-model', [])
.directive('checklistModel', ['$parse', '$compile', function($parse, $compile) {
// contains
function contains(arr, item) {
if (angular.isArray(arr)) {
for (var i = 0; i < arr.length; i++) {
if (angular.equals(arr[i], item)) {
return true;
}
}
}
return false;
}
// add
function add(arr, item) {
arr = angular.isArray(arr) ? arr : [];
for (var i = 0; i < arr.length; i++) {
if (angular.equals(arr[i], item)) {
return;
}
}
arr.push(item);
}
// remove
function remove(arr, item) {
if (angular.isArray(arr)) {
for (var i = 0; i < arr.length; i++) {
if (angular.equals(arr[i], item)) {
arr.splice(i, 1);
return;
}
}
}
}
return {
restrict: 'A',
scope: true,
link: function(scope, elem, attrs) {
if (elem[0].tagName !== 'INPUT' || !elem.attr('type', 'checkbox')) {
throw 'checklist-model should be applied to `input[type="checkbox"]`.';
}
if (!attrs.checklistValue) {
throw 'You should provide `checklist-value`.';
}
// link to original model. Initially assigned in $watch
var model;// = modelGet(scope);
var value = $parse(attrs.checklistValue)(scope.$parent);
// local var storing individual checkbox model
// scope.checked - will be set in $watch
// exclude recursion
elem.removeAttr('checklist-model');
elem.attr('ng-model', 'checked');
$compile(elem)(scope);
// watch UI checked change
scope.$watch('checked', function(newValue, oldValue) {
if (newValue === oldValue) {
return;
} if (newValue === true) {
add(model, value);
} else if (newValue === false) {
remove(model, value);
}
});
// watch element destroy to remove from model
elem.bind('$destroy', function() {
remove(model, value);
});
// watch model change
scope.$parent.$watch(attrs.checklistModel, function(newArr, oldArr) {
// need this line to keep link with original model
model = newArr;
scope.checked = contains(newArr, value);
}, true);
}
};
}]);