Knockout检查了绑定问题

时间:2012-02-17 19:40:59

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

我遇到了与KnockoutJS 2.0不兼容的复选框绑定问题。我有一个对象数组。这些对象的一个​​属性是不同对象的数组。在子对象中有一些属性,其中一个属性是布尔值。我为每个父对象构建一个列表,并在每个父对象下显示子对象。对于每个孩子列表,我有两个视图,一个只读和一个编辑视图。在只读中,我有图像表示是否根据布尔属性检查项目。这是有效的,如果我通过控制台更新布尔值,我会看到我期望的 - 图像消失或根据我指定的值显示。在编辑视图中,图像将替换为复选框。当我通过控制台更新值时,我看到相同的行为 - 它会在我预期的时候被检查,而不是在我没有的时候。当我选中或取消选中复选框时,会出现问题。执行此操作不会更改复选框绑定的基础值。

这是我数据的基本概念。

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

这是绑定

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

3 个答案:

答案 0 :(得分:3)

问题是&#34;检查&#34;这是双向绑定:需要读取绑定属性以生成正确的视图,但是当您单击复选框时也需要更新。将此与对象绑定对比:

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

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

因此,您需要直接绑定到observable属性,而不需要&#34;展开&#34;它添加&#39;()&#39;,它将在需要时通过淘汰完成,包括读写:

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

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

如果您需要否定该值(以便在值为false时选中复选框),您可以添加可写的计算可观察量,如http://knockoutjs.com/documentation/computedObservables.html部分&#34;可写计算的可观察量&#34所述;或者您可以否定viewmodel中的数据,在发送数据之前在服务器上执行此操作,或者在填充viewmodel之前在客户端上执行此操作。

希望这会有所帮助。

答案 1 :(得分: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);
};

我会忽略任何说我不应该修改内置对象原型的评论;我会做的,因为我该死的好了 - - )。

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

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

希望这有助于某人。

答案 2 :(得分:0)

我放弃了尝试让它与bool值一起工作并创建了一个选定对象的数组并以这种方式处理它。这不是最佳解决方案,但我厌倦了与此作斗争。