使用脚本检查每个复选框时,Knockout模型不会更新

时间:2013-07-09 20:09:47

标签: javascript jquery knockout.js

我有一系列复选框,这些复选框都绑定到选定值数组:

var myModel = {
   // ...
   workgroupsImpacted: ko.observableArray([])
};

在顶部,我有一个全选复选框。选中全选复选框后,运行以下代码:

var subGroups = $('#WorkgroupCB_' + parentId);
$(':input', subGroups).prop('checked', this.checked);

检查(或取消选中)相应的复选框控件。这很有用,但是UI明智,但绑定的模型不会更新。换句话说,workgroupsImpacted仍为空。

当我检查取消选中一堆复选框时,是否有一种简单的方法来更新模型?或者,我是否必须遍历每个复选框,挖掘值,并在我的模型中手动添加或删除数组中的值?我希望Knockout.js能够轻松地提供一种标准机制。

4 个答案:

答案 0 :(得分:2)

KnockoutJS中,observable array只跟踪数组中的项目数量并报告更改(即添加/删除项目),但它不会跟踪对象的状态在那个阵列中。

听起来你想拥有observable array observables。你有一个代表列表中每个checkbox的模型对象吗?

以下是fiddle,其中显示了对observable array内的复选框的跟踪。

答案 1 :(得分:1)

你不应该使用jquery来做到这一点。

你应该只有一个代表复选框的模型,其中包含一个代表复选框状态的ko.observable。要检查所有内容,您只需要遍历复选框并将ko.observable更改为true。

答案 2 :(得分:1)

您应创建一个可写的计算observable来表示“全部选中”复选框。这是一个例子:

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
});

我已经将an answer写成了一个类似的问题,该问题详细介绍了上面的例子,包括这个jsFiddle:http://jsfiddle.net/mbest/L3LeD/

在write函数中,如果要使用每个项的属性填充所选items数组,可以使用:

this.selectedItems(value ?
    ko.utils.arrayMap(this.items(), function(item) { return item.property; }) :
    [] );

答案 3 :(得分:1)

我知道您不希望维护模型中的项目列表。在Knockout中仍然可以使用这种情况,方法是使用自定义绑定。

这是我放在一起的,它将使用click更新复选框(因为这是Knockout所关注的)。为了确保“check all”复选框是最新的,它会监视对数组的更改(只需在update函数中访问它),然后只查找任何未选中的复选框。

ko.bindingHandlers.allChecked = {
    init: function(element, valueAccessor) {
        $(element).click(function() {
            $(valueAccessor().selector)
                .filter(element.checked ? ':not(:checked)' : ':checked')
                .click();
        });
    },
    update: function(element, valueAccessor) {
        var value = valueAccessor(),
            watch = ko.unwrap(value.watch),
            unchecked = $(value.selector).filter(':not(:checked)');
        element.checked = (unchecked.length === 0);
    }
};

将它绑定到一个复选框输入元素,如下所示:

<input type="checkbox" data-bind="
    allChecked: {
        selector: '#checks input:checkbox', 
        watch: selectedItems}" />

jsFiddle:http://jsfiddle.net/mbest/nth7A/