【问题标题】:Knockout checked binding issue淘汰赛检查绑定问题
【发布时间】:2012-02-17 19:40:58
【问题描述】:

我遇到了一个问题,即复选框绑定不能很好地与 KnockoutJS 2.0 一起使用。我有一个对象数组。这些对象的属性之一是一组不同的对象。在子对象中有一些属性,其中之一是布尔值。我为每个父对象建立一个列表,并在每个父对象下显示子对象。对于每个孩子的列表,我有两个视图,一个只读视图和一个编辑视图。在只读中,我有代表是否基于布尔属性检查项目的图像。这可行,如果我通过控制台更新布尔值,我会看到我所期望的——图像消失或根据我分配的值显示。在编辑视图中,图像被替换为复选框。当我通过控制台更新值时,我看到了相同的行为——当我期望它是时检查它,而不是当我不检查它时。当我选中或取消选中该复选框时,问题就出现了。这样做不会更改复选框绑定到的基础值。

这是我的数据的基本概念。

[
    {
        "xxx": "yyy",
        "xxx": "yyy",
        ...
        "Displays": [
            {
            "xxx": "yyy",
            ...
                "Excluded": false,
            },
            {
            "xxx": "yyy",
             ...
                "Excluded": true,
            }
        ],
    }
]

这是绑定

<input type="checkbox" data-bind="checked: !Excluded()" />

【问题讨论】:

  • 尝试从绑定中删除 ()(选中:已排除)。仅当您在可观察属性上评估表达式时才需要它,在这种情况下,您的 Excluded 属性甚至不是可观察的。
  • 这是一个可观察的,我只是没有发布代码使其成为可观察的。

标签: asp.net-mvc-3 knockout.js


【解决方案1】:

问题是这里的“checked”是双向绑定:需要读取绑定的属性才能生成正确的视图,但也需要在单击复选框时进行更新。将此与以下绑定进行对比:

<span data-bind="text: 'your name is ' + name()"></span>

当仅读取表达式时,您可以使用表达式(并且您需要解开 observable)。

因此,您需要直接绑定到 observable 属性,而不是“解包”它添加 '()',它会在需要时通过敲除来完成,无论是读取还是写入:

<input type="checkbox" data-bind="checked: Excluded" />

有关简单示例,请参阅http://jsfiddle.net/saurus/usKwA/。请注意复选框标签是如何在更改时更新的,这表明模型已更新并且渲染触发正确。

如果您需要取反值(以便在值为 false 时选中复选框),您可以添加一个可写的计算 observable,如 http://knockoutjs.com/documentation/computedObservables.html 部分“可写计算 observables”中所述,或者您可以取反视图模型中的数据,在发送数据之前在服务器上执行,或者在填充视图模型之前在客户端执行。

希望这会有所帮助。

【讨论】:

  • 如果我不使用括号,它根本不起作用。复选框永远不会被选中,并且检查它们不会更新 observable。
【解决方案2】:

我知道我的答案在这里的游戏有点晚了,但是我今天遇到了这个问题,这是我能找到的与该问题最接近的线程,而且似乎没有解决它的答案。所以这是我的解决方案。

本质上,问题在于,knockout 确实希望您的 viewModel 值是字符串,而不是布尔值,但这并不总是实用的。因此,我创建了一个名为“isChecked”的绑定,它严格使用布尔值。 注意:这仅适用于可观察的属性。

ko.bindingHandlers.isChecked = {
    getElementDeclaredValue: function (element) {
        var declaredValue = element.getAttribute("value");

        // If a value is provided, we presume it represents "true",
        // unless its explicitly "false". If no value is provided, we
        // presume that a checked state would equal "true".
        return declaredValue && Boolean.isBool(declaredValue)
            ? Boolean.parse(declaredValue)
            : true;
    },

    init: function (element, valueAccessor) {
        var updateHandler = function () {
            var declaredValue = ko.bindingHandlers.isChecked.getElementDeclaredValue(element);
            var elementValue = element.checked ? declaredValue : !declaredValue;

            var modelValue = valueAccessor();
            var currentValue = ko.utils.unwrapObservable(modelValue);

            if (elementValue === currentValue)
                return;

            if (ko.isObservable(modelValue)) {
                modelValue(elementValue);
            }
        };

        ko.utils.registerEventHandler(element, "click", updateHandler);
    },

    update: function (element, valueAccessor) {
        var elementValue = ko.bindingHandlers.isChecked.getElementDeclaredValue(element);
        element.checked = elementValue === ko.utils.unwrapObservable(valueAccessor());
    }
};

两个布尔方法(“parse”和“isBool”)定义如下:

Boolean.isBool = function (value) {
    return (/^(?:true|false)$/i).test(value);
};

Boolean.parse = function (value) {
    return (/^true$/i).test(value);
};

我将忽略任何说我不应该修改内置对象原型的 cmets;我会尽我所能;-)。

用法与检查绑定相同。 “value”属性是可选的,除非您希望选中状态表示 false:

<input type="radio" id="rbNewClaim" name="ClaimType" value="false" data-bind="checked: isExistingClaim" />

希望这对某人有所帮助。

【讨论】:

    【解决方案3】:

    我放弃了尝试让它与布尔值一起使用,并创建了一个选定对象的数组并以这种方式处理它。这不是最佳解决方案,但我已经厌倦了与之抗争。

    【讨论】:

      猜你喜欢
      • 2014-09-18
      • 2014-03-30
      • 2013-03-06
      • 2016-11-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多