如何阻止Knockout清除复选框?

时间:2015-09-11 15:12:02

标签: knockout.js

如何停止Knockout清除复选框?

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>

我希望服务器不断更新以更新表,但复选框应该独立于此;我不想将复选框状态发送到服务器,然后将其与更新合并。

1 个答案:

答案 0 :(得分:1)

复选框未被清除,它们正在重新绘制。您可以使用foreach绑定根据observableArrays中的内容生成它们。每个“服务器提取”都会替换数组中的数据,因此您将获得新的框。

如果您希望绘制的项目持续存在,则除了丢弃和替换所有数据之外,您还必须执行其他操作。例如,当新数据进入时,您只删除不再表示的项目,并添加任何新项目。

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>