【问题标题】:When checking every checkbox with script, Knockout model does not get updated使用脚本检查每个复选框时,Knockout 模型不会更新
【发布时间】:2013-07-10 09:43:27
【问题描述】:

我有一系列复选框,它们都绑定到一个选定值的数组:

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

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

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

这会选中(或取消选中)相应的复选框控件。这很好用,UI 明智,但是绑定模型没有得到更新。换句话说,workgroupsImpacted 保持为空。

当我选中取消选中一堆复选框时,有没有一种简单的方法来更新模型?或者,我是否必须遍历每个复选框,挖掘值,然后从模型中的数组中手动​​添加或删除该值?我希望 Knockout.js 提供一个标准机制来轻松完成此操作。

【问题讨论】:

  • 如果您选中其中一个复选框,workgroupsImpacted 会更新吗?如果是这样,这是怎么发生的?
  • @MichaelBest - 是的,每个单独的复选框都绑定到 workgroupsImpacted 数组。但是,复选框是在服务器上呈现的,而不是使用 foreach 模板。

标签: javascript jquery knockout.js


【解决方案1】:

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

听起来您想要一个 observable arrayobservables。你有代表列表中每个checkbox 的模型对象吗?

这是一个fiddle,它显示了observable array 中复选框的跟踪。

【讨论】:

  • 谢谢!我认为答案基本上是我需要更新模型,而不是 DOM;这是我怀疑的。问题是复选框来自数据库(并呈现为 HTML),实际上更像是一个复选框 tree。我想检查一个父节点并选择所有叶节点。尝试使用该复选框层次结构构建模型将相当复杂,因为客户端不知道该信息。我可能必须解析 DOM 并构建 JSON 表示,或者通过 AJAX 查询服务器;我都不想做。
【解决方案2】:

您不应该使用 jquery 来执行此操作。

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

【讨论】:

    【解决方案3】:

    您应该创建一个可写的计算 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/

    在写函数中,如果你想用每个项目的属性填充你选择的项目数组,你可以使用这个:

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

    【讨论】:

    • 这将很难,因为我有不确定数量的“检查所有”复选框。我必须解析 DOM,然后从中构建模型,我觉得这有点令人费解。
    • 好的。这是一个奇怪的情况。 Knockout 假定 DOM 依赖于模型,而不是相反。也许你只需要使用 Knockout 以外的东西(比如普通的 jQuery)。
    • 好吧,我可能会做一个 AJAX 查询,以便在页面加载后从服务器加载所有 UI 数据。然后,从那里创建我的模型,然后创建 DOM。我决定不这样做,因为使用 ASP.NET Repeater 控件很容易创建复选框。
    • 我添加了另一个我认为更适合您的情况的答案。
    【解决方案4】:

    我了解您不想维护模型中的项目列表。在 Knockout 中仍然可以处理这种情况,方法是使用自定义绑定。

    这是我整理的一个,它将使用click 更新复选框(因为这是 Knockout 所关注的)。为确保“全选”复选框是最新的,它会监视数组的更改(只需在 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/

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-10-30
      • 2018-07-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-10-05
      • 1970-01-01
      • 2018-04-07
      相关资源
      最近更新 更多