In questo esempio, per Knockout JS, mostro come implementare la selezione / deselezione di tutti gli elementi di una lista di checkbox.

Partendo dal precedente Checkbox list in Knockout JS, per prima cosa va aggiunto, nell'html, la voce Seleziona tutti (select all):

HTML

<div>
    <label>
        <input type="checkbox" data-bind="checked: selectAll">
        <span>Seleziona tutti</span>
    </label>
</div>
questa checkbox è in bind con la proprietà observable, di tipo computed, con nome selectAll:

JavaScript

function CheckboxAllViewModel() {
    var self = this;
    ...
    self.selectAll = ko.computed({
        read: function () {
            return self.items().length === self.selectedItems().length;
        },
        write: function (newState) {
            self.selectedItems.removeAll();
            if (newState == true) {
                var selected = [];
                var items = self.items();
                items.forEach(function (item) {
                    selected.push(item.id);
                });
                ko.utils.arrayPushAll(self.selectedItems, selected);
            }
        }
    });
}
Il metodo read si occupa di calcolare lo stato, true/false, in funzione del numero di elementi selezionati.
Se il numero degli elementi presenti ( self.items().length ) coincide con gli elementi selezionati ( self.selectedItems().length ), ovvero sono tutti selezionati, ritorno true e la checkbox è selezionata, negli altri casi ritorno false.

Il metodo write viene invocato quando scatta l'evento click sulla checkbox.
In questo caso, prima, per semplicità, cancello tutti gli elementi selezionati ( self.selectedItems.removeAll() ), poi ciclo su tutti gli elementi e li seleziono ( selected.push(item.id) ), infine li assegno ( ko.utils.arrayPushAll ).

L'html completo è questo:

HTML

<div id="sgart-app-ko-checkbox-list" class="app-ko">
    <div>
        <label>
            <input type="checkbox" data-bind="checked: selectAll">
            <span>Seleziona tutti</span>
        </label>
    </div>
    <ul data-bind="foreach: items">
        <li>
            <label>
                <input type="checkbox" data-bind="checkedValue: id, checked: $parent.selectedItems">
                <span data-bind="text:description"></span>
            </label>
        </li>
    </ul>
    <div>Selected id: <span data-bind="text: selectedItems"></span></div>

    <!-- visualizza il JSON del view-moel -->
    <div style="margin-top:20px;">Json: <span data-bind="text: ko.toJSON($root)"></span></div>
</div>
e il corrispondente JavaScript è questo:

JavaScript

// view-model
function CheckboxAllViewModel() {
    var self = this;

    self.items = ko.observableArray();
    self.selectedItems = ko.observableArray();
    self.selectAll = ko.computed({
        read: function () {
            return self.items().length === self.selectedItems().length;
        },
        write: function (newState) {
            self.selectedItems.removeAll();
            if (newState == true) {
                var selected = [];
                var items = self.items();
                items.forEach(function (item) {
                    selected.push(item.id);
                });
                ko.utils.arrayPushAll(self.selectedItems, selected);
            }
        }
    });
}

// eseguo il codice dopo il load del DOM
document.addEventListener("DOMContentLoaded", function () {
    // dati iniziali
    var exampleItems = [
        { id: 1, description: "Scelta A" },
        { id: 21, description: "Scelta B" },
        { id: 4, description: "Scelta C" },
    ];
    
    // istanzio un nuovo view-model
    var vm = new CheckboxAllViewModel();
    ko.utils.arrayPushAll(vm.items, exampleItems);

    // recupero il template della view
    var view = document.getElementById("sgart-app-ko-checkbox-list");
    
    // binding tra view e view-model
    ko.applyBindings(vm, view);

    // eventuale preselezione degli item
    // vm.selectedItems.push(21);
});
Questo è il risultato:
mentre questo è l'esempio funzionante:
Selected id:
Json:

Da notare:
  • l'uso del metodo ko.utils.arrayPushAll(<observableArray>, <array>) per caricare in un solo colpo e in modo più efficiente, un intero array in una proprietà observableArray
  • il metodo <observableArray>.removeAll() per rimuovere tutti gli elementi da un observableArray
  • oppure il metodo ko.toJSON($root) per visualizzare una rappresntazione JSON del view-model
  • in fine ko.computed per creare delle proprietà observable calcolate
Tags:
Esempi224 JavaScript184 Knockout js8 MVVM6
Potrebbe interessarti anche: