Checklist-model

AngularJS directive for list of checkboxes

Why this is needed?

In Angular one checkbox <input type="checkbox" ng-model="..."> is linked with one model. But in practice we usually want one model to store array of checked values from several checkboxes. Checklist-model solves that task without additional code in controller. You should play with attributes of <input type="checkbox"> tag:

  1. set checklist-model instead of ng-model
  2. set checklist-value - what should be picked as array item

Please, try out demos below:

Array of primitives

demo

user.roles

{{user.roles|json}}

html

<label ng-repeat="role in roles">
  <input type="checkbox" checklist-model="user.roles" checklist-value="role"> {{role}}
</label>

js

var app = angular.module("app", ["checklist-model"]);
app.controller('Ctrl1', function($scope) {
  $scope.roles = [
    'guest', 
    'user', 
    'customer', 
    'admin'
  ];
  $scope.user = {
    roles: ['user']
  };
  $scope.checkAll = function() {
    $scope.user.roles = angular.copy($scope.roles);
  };
  $scope.uncheckAll = function() {
    $scope.user.roles = [];
  };
  $scope.checkFirst = function() {
    $scope.user.roles.splice(0, $scope.user.roles.length); 
    $scope.user.roles.push('guest');
  };
});

Array of objects (pick id)

demo

user.roles

{{user.roles|json}}

html

<label ng-repeat="role in roles">
  <input type="checkbox" checklist-model="user.roles" checklist-value="role.id"> {{role.text}}
</label>

js

var app = angular.module("app", ["checklist-model"]);
app.controller('Ctrl2', function($scope) {
  $scope.roles = [
    {id: 1, text: 'guest'},
    {id: 2, text: 'user'},
    {id: 3, text: 'customer'},
    {id: 4, text: 'admin'}
  ];
  $scope.user = {
    roles: [2, 4]
  };
  $scope.checkAll = function() {
    $scope.user.roles = $scope.roles.map(function(item) { return item.id; });
  };
  $scope.uncheckAll = function() {
    $scope.user.roles = [];
  };
  $scope.checkFirst = function() {
    $scope.user.roles.splice(0, $scope.user.roles.length); 
    $scope.user.roles.push(1);
  };
});

Array of objects (pick object)

demo

user.roles

{{user.roles|json}}

html

<label ng-repeat="role in roles">
  <input type="checkbox" data-checklist-model="user.roles" data-checklist-value="role"> {{role.text}}
</label>

js

var app = angular.module("app", ["checklist-model"]);
app.controller('Ctrl3', 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() {
    $scope.user.roles = angular.copy($scope.roles);
  };
  $scope.uncheckAll = function() {
    $scope.user.roles = [];
  };
  $scope.checkFirst = function() {
    $scope.user.roles = [];
    $scope.user.roles.push($scope.roles[0]);
  };
  $scope.setToNull = function() {
    $scope.user.roles = null;
  };

});

Array of only one object

demo

user.roles

{{user.roles|json}}

html

<label ng-repeat="role in roles">
  <input type="checkbox" data-checklist-model="user.roles" data-checklist-value="role"> {{role.text}}
</label>

js

var app = angular.module("app", ["checklist-model"]);
app.controller('Ctrl7', function($scope) {
  $scope.roles = [
    {id: 1, text: 'guest'}
  ];
  $scope.user = {
    roles: [$scope.roles[0]]
  };
  $scope.checkAll = function() {
    $scope.user.roles = angular.copy($scope.roles);
  };
  $scope.uncheckAll = function() {
    $scope.user.roles = [];
  };
  $scope.checkFirst = function() {
    $scope.user.roles.splice(0, $scope.user.roles.length); 
    $scope.user.roles.push($scope.roles[0]);
  };
});

Object properties

demo

user.roles

{{user.roles|json}}

html

<label ng-repeat="(key, text) in roles">
  <input type="checkbox" checklist-model="user.roles" checklist-value="key"> {{text}}
</label>

js

var app = angular.module("app", ["checklist-model"]);
app.controller('Ctrl4', function($scope) {
  $scope.roles = {
    a: 'Administrator',
    c: 'Customer',
    g: 'Guest',
    u: 'User'
  };
  $scope.user = {
    roles: ['c']
  };
  $scope.checkAll = function() {
    $scope.user.roles = Object.keys($scope.roles);
  };
  $scope.uncheckAll = function() {
    $scope.user.roles = [];
  };
  $scope.checkFirst = function() {
    $scope.user.roles.splice(0, $scope.user.roles.length); 
    $scope.user.roles.push('a');
  };
});

Static list of objects (without ng-repeat)

demo

user.roles

{{user.roles|json}}

html

<label><input type="checkbox" checklist-model="user.roles" value="a"> Administrator</label>
<label><input type="checkbox" checklist-model="user.roles" value="c"> Customer</label>
<label><input type="checkbox" checklist-model="user.roles" value="g"> Guest</label>
<label><input type="checkbox" checklist-model="user.roles" value="u"> User</label>

js

var app = angular.module("app", ["checklist-model"]);
app.controller('Ctrl4a', function($scope) {
  $scope.roles = {
    a: 'Administrator',
    c: 'Customer',
    g: 'Guest',
    u: 'User'
  };
  $scope.user = {
    roles: ['c']
  };
  $scope.checkAll = function() {
    $scope.user.roles = Object.keys($scope.roles);
  };
  $scope.uncheckAll = function() {
    $scope.user.roles = [];
  };
  $scope.checkFirst = function() {
    $scope.user.roles.splice(0, $scope.user.roles.length); 
    $scope.user.roles.push('a');
  };
});

Use a function as checklist-model

demo

getRoles()

{{getRoles()|json}}

html

<label ng-repeat="role in roles">
  <input type="checkbox" checklist-model="getRoles()" checklist-value="role" ng-change="check(role, checked)"> {{role}}
</label>

js

var app = angular.module("app", ["checklist-model"]);
app.controller('Ctrl8', function($scope) {
  $scope.roles = [
    'guest', 
    'user', 
    'customer', 
    'admin'
  ];
  $scope.user = {
    roles: ['user']
  };
  $scope.checkAll = function() {
    $scope.user.roles = angular.copy($scope.roles);
  };
  $scope.uncheckAll = function() {
    $scope.user.roles = [];
  };
  $scope.checkFirst = function() {
    $scope.user.roles.splice(0, $scope.user.roles.length); 
    $scope.user.roles.push('guest');
  };
  $scope.getRoles = function() {
    return $scope.user.roles;
  };
  $scope.check = function(value, checked) {
    var idx = $scope.user.roles.indexOf(value);
    if (idx >= 0 && !checked) {
      $scope.user.roles.splice(idx, 1);
    }
    if (idx < 0 && checked) {
      $scope.user.roles.push(value);
    }
  };
});

Array of object, specifying also the ngModel attribute

demo

user.roles

{{user.roles|json}}

html

<label ng-repeat="role in roles">
  <input type="checkbox" checklist-model="user.roles" checklist-value="role" ng-model="justAnotherCheckedVar"> {{role.text}}
</label>

js

var app = angular.module("app", ["checklist-model"]);
app.controller('Ctrl3a', 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() {
    $scope.user.roles = angular.copy($scope.roles);
  };
  $scope.uncheckAll = function() {
    $scope.user.roles = [];
  };
  $scope.checkFirst = function() {
    $scope.user.roles.splice(0, $scope.user.roles.length); 
    $scope.user.roles.push($scope.roles[0]);
  };
});

Comparator

demo

selectedUsers

{{selectedUsers|json}}

html

<label ng-repeat="user in users">
  <input type="checkbox" checklist-model="selectedUsers" checklist-value="user" checklist-comparator="compareFn"> {{user.name}}
</label>

js

var app = angular.module("app", ["checklist-model"]);
app.controller('Ctrl6', function($scope) {
    $scope.users = [
        {id: 1, name: 'Aaron'},
        {id: 2, name: 'David'},
        {id: 3, name: 'Moses'}
    ];

    $scope.selectedUsers = [];

    $scope.compareFn = function(obj1, obj2){
        return obj1.id === obj2.id;
    };

    $scope.checkFirst = function() {
        $scope.selectedUsers.splice(0, $scope.selectedUsers.length, $scope.users[0]);
    };

    $scope.checkAll = function() {
        $scope.selectedUsers.splice(0, $scope.selectedUsers.length);
        for (var i in $scope.users) {
             $scope.selectedUsers.push($scope.users[i]);
        }
    };

    $scope.uncheckAll = function() {
        $scope.selectedUsers.splice(0, $scope.selectedUsers.length);
    }
});

Comparator expression

demo

selectedUsers

{{selectedUsers|json}}

html

<label ng-repeat="user in users">
  <input type="checkbox" checklist-model="selectedUsers" checklist-value="user" checklist-comparator=".id"> {{user.name}}
</label>

js

var app = angular.module("app", ["checklist-model"]);
app.controller('Ctrl6a', function($scope) {
    $scope.users = [
        {id: 1, name: 'Aaron'},
        {id: 2, name: 'David'},
        {id: 2, name: 'Moses'}
    ];

    $scope.selectedUsers = [];

    $scope.checkFirst = function() {
        $scope.selectedUsers.splice(0, $scope.selectedUsers.length, $scope.users[0]);
    };

    $scope.checkAll = function() {
        $scope.selectedUsers.splice(0, $scope.selectedUsers.length);
        for (var i in $scope.users) {
             $scope.selectedUsers.push($scope.users[i]);
        }
    };

    $scope.uncheckAll = function() {
        $scope.selectedUsers.splice(0, $scope.selectedUsers.length);
    }
});

Event

demo

testValue

{{testValue|json}}

html

<label ng-repeat="(key, text) in roles">
  <input type="checkbox" checklist-before-change="shouldChange(key)" checklist-change="imChanged()" checklist-model="user.roles" checklist-value="key"> {{text}}
</label>

js

var app = angular.module("app", ["checklist-model"]);
app.controller('Ctrl5', function($scope) {
  $scope.roles = {
    a: 'Administrator',
    c: 'Customer',
    g: 'Guest',
    u: 'User'
  };

  $scope.testValue = 'Im not changed yet!';
  $scope.imChanged = function(){
    $scope.testValue = $scope.user.roles.join(',');
  }
  $scope.shouldChange = function(key){
console.log("should change " + key);
    return key !== "g";
  }

  $scope.user = {
    roles: ['c']
  };

  $scope.checkFirst = function() {
    $scope.user.roles.splice(0, $scope.user.roles.length);
    $scope.user.roles.push('a');
  };

  $scope.uncheckAll = function() {
    $scope.user.roles.splice(0, $scope.user.roles.length);
  };

  $scope.checkAll = function() {
    $scope.user.roles.splice(0, $scope.user.roles.length);
    for (var r in $scope.roles) {
      $scope.user.roles.push(r);
    }
  };

});