checkedInArray and allItemsSelected example

HTML

<div>
    <input type="checkbox" data-bind="checked: allItemsSelected" />
    Check All
</div>

<div data-bind="foreach: items">
    <div>
        <input type="checkbox" data-bind="checkedInArray: { array: $parent.selectedItems, value: $data }" />
        <span data-bind="text: name"></span>
    </div>
</div>

JavaScript

// ko.utils.addOrRemoveItem isn't included until version 2.3.0
if (!ko.utils.addOrRemoveItem) {
    ko.utils.addOrRemoveItem = function(array, value, included) {
        var existingEntryIndex = array.indexOf ? array.indexOf(value) : ko.utils.arrayIndexOf(array, value);
        if (existingEntryIndex < 0) {
            if (included)
                array.push(value);
        } else {
            if (!included)
                array.splice(existingEntryIndex, 1);
        }
    };
}

ko.bindingHandlers.checkedInArray = {
    init: function (element, valueAccessor) {
        ko.utils.registerEventHandler(element, "click", function() {
            var options = ko.utils.unwrapObservable(valueAccessor()),
                array = options.array, // don't unwrap array because we want to update the observable array itself
                value = ko.utils.unwrapObservable(options.value),
                checked = element.checked;
            ko.utils.addOrRemoveItem(array, value, checked);
        });
    },
    update: function (element, valueAccessor) {
        var options = ko.utils.unwrapObservable(valueAccessor()),
            array = ko.utils.unwrapObservable(options.array),
            value = ko.utils.unwrapObservable(options.value);
        
        element.checked = ko.utils.arrayIndexOf(array, value) >= 0;
    }
};

function ViewModel() {
    for (var items = [], i = 0; i < 500; i++) {
        items[i] = {
            id: i,
            name: 'Item ' + i
        };
    }

    this.items = ko.observableArray(items);
    this.selectedItems = ko.observableArray();
    this.allItemsSelected = ko.computed({
        read: function() {
            return this.selectedItems().length === this.items().length;
        },
        write: function(value) {
            this.selectedItems(value ? this.items.slice(0) : [] );
        },
        owner: this
    });
}

ko.applyBindings(new ViewModel());