Reputation: 1121
How do I stop Knockout from clearing the checkboxes?
https://jsfiddle.net/mezv2tns/
var vm = {
state: ko.observable({
'success': true,
'items': [{'name': 'abc'}, {'name': 'def'}]
}),
items: ko.observableArray([{'name': 'abc'}, {'name': 'def'}]),
itemsMapping: ko.observableArray([{'name': 'abc'}, {'name': 'def'}]),
};
$(function() {
console.log('go');
ko.applyBindings(vm, $('#a')[0]);
setInterval(function() {
console.log('update');
// Imagine this is coming from an Ajax request.
var dataFromServer = [{'name': 'abc'}, {'name': 'def'}, {'name': 'new'}];
var stateFromServer = {'success': true, 'items': dataFromServer};
// Update the observables using different techniques.
vm.state(stateFromServer);
vm.items(dataFromServer);
ko.mapping.fromJS(dataFromServer, {}, vm.itemsMapping);
}, 1000);
});
HTML:
<table data-bind="foreach: state().items">
<tr><td><input type="checkbox"></td><td><span data-bind="text: name"></span></td></tr>
</table>
I want the constant updates from the server to update the table but the checkboxes should be independent of that; I don't want to send the checkbox state to the server and then have it merge it with the updates.
Upvotes: 1
Views: 81
Reputation: 43899
The checkboxes aren't being cleared, they're being redrawn. You use a foreach
binding to generate them according to what you have in your observableArrays. Each "server fetch" replaces the data in the arrays, so you get new boxes.
If you want the items that are drawn to persist, you'll have to do something other than throwing away and replacing all the data. For example, when new data comes in, you delete only items that are no longer represented, and add any that are new.
var initialData = [{'name': 'abc'}, {'name': 'def'}];
var vm = {
state: ko.observable({
'success': true,
'items': initialData
}),
items: ko.observableArray(initialData),
itemsMapping: ko.observableArray(initialData),
persistentItems: ko.observableArray(initialData)
};
function updatePersistent(newData) {
// Delete any that are not in newData (not implemented)
// Add any that are not already here
for (var i=0; i<newData.length; ++i) {
if (!found(newData[i])) vm.persistentItems.push(newData[i]);
}
}
function found(item) {
var items = vm.persistentItems();
for (var i=0; i<items.length; ++i) {
if (items[i].name == item.name) return true;
}
return false;
}
$(function() {
console.log('go');
ko.applyBindings(vm, $('#a')[0]);
setInterval(function() {
console.log('update');
// Imagine this is coming from an Ajax request.
var dataFromServer = [{'name': 'abc'}, {'name': 'def'}, {'name': 'new'}];
var stateFromServer = {'success': true, 'items': dataFromServer};
// Update the observables using different techniques.
vm.state(stateFromServer);
vm.items(dataFromServer);
ko.mapping.fromJS(dataFromServer, {}, vm.itemsMapping);
updatePersistent(dataFromServer);
}, 1000);
});
div div {
border: 1px solid black;
text-align: center;
margin: 1px;
height: 50px;
}
h1 {
font-size: 1em;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.1.0/knockout-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout.mapping/2.4.1/knockout.mapping.min.js"></script>
<div id="a">
<h1>Desired Technique</h1>
<table data-bind="foreach: state().items">
<tr><td><input type="checkbox"></td><td><span data-bind="text: name"></span></td></tr>
</table>
<hr>
<h1>Technique 2</h1>
<table data-bind="foreach: items()">
<tr><td><input type="checkbox"></td><td><span data-bind="text: name"></span></td></tr>
</table>
<hr>
<h1>Technique 3</h1>
<table data-bind="foreach: itemsMapping()">
<tr><td><input type="checkbox"></td><td><span data-bind="text: name"></span></td></tr>
</table>
<h1>Persistent</h1>
<table data-bind="foreach: persistentItems">
<tr><td><input type="checkbox"></td><td><span data-bind="text: name"></span></td></tr>
</table>
</div>
Upvotes: 1