3

对于复选框和单选按钮,我有相同的数据结构。选中复选框时,它们会返回正确的布尔值(“选择”变量)。

但是,当我检查单选按钮时,“选择”总是更改为“值”(整数)。

此外,即使 'chosen' == true,单选按钮在开始时也不会被“选中”

Javascript:

function attributeValueViewModel(data) {
    var self = this;
    self.id = ko.observable(data.id);
    self.attributeID = ko.observable(data.attributeID);
    self.value = ko.observable(data.value);
    self.chosen = ko.observable(data.chosen);
}

function viewModel() {
    var self = this;
    self.attributeValues1 = ko.observableArray([]);
    self.attributeValues2 = ko.observableArray([]);
    self.addToList = function(data) {
        ko.utils.arrayForEach(data, function(item) {           
            self.attributeValues1.push(new attributeValueViewModel(item));
            self.attributeValues2.push(new attributeValueViewModel(item));
        });
    };
}

var arr = [
    {
        "id": 55,
        "attributeID": 28,
        "value": "Yes",
        "chosen": false,
    },
    {
        "id": 56,
        "attributeID": 28,
        "value": "No",
        "chosen": true,
    },
    {
        "id": 62,
        "attributeID": 28,
        "value": "Maybe",
        "chosen": false,
    }
];

var vm = new viewModel();
ko.applyBindings(vm);
vm.addToList(arr);

HTML

<b>Checkbox:</b>
<div id="test1">
    <span data-bind="foreach: attributeValues1()">
    <input type="checkbox" data-bind="value: id(), checked: chosen, attr: { name: 'test1' }" />
    <span data-bind="text: value()"></span>
    <span data-bind="text: chosen()"></span>
    </span>
</div>
<br />
<b>Radio:</b>
<div id="test2">
    <span data-bind="foreach: attributeValues2()">
    <input type="radio" data-bind="value: id(), checked: chosen, attr: { name: 'test2' }" />
    <span data-bind="text: value()"></span>
    <span data-bind="text: chosen()"></span>
    </span>
</div>​

这是我的小提琴:http: //jsfiddle.net/SN7Vn/1/

您能否解释一下这种行为以及为什么单选按钮不更新布尔值(就像复选框一样)?

4

2 回答 2

5

复选框和单选按钮的行为彼此不同。当单个 observable 绑定到checked绑定(而不是数组)时,它们的行为特别不同。

对于复选框,它将始终是一个布尔值,指示它是否被选中。简单的。如果是数组,value则将从数组中添加/删除。

但是对于单选按钮,它将是分配给单选按钮的值。对于单个 observable,它只会被认为已检查它绑定的值是否等于该值。在您的情况下,您的值绑定到所以只有当值等于相应的 idid时才会响应。chosen对于数组,它将向数组添加/删除值。

由于没有其他东西改变chosen相应属性的值,所以它保持不变

我调整了您的示例以演示该值如何影响检查状态。 更新的小提琴

这一切都在文档中详细说明,请仔细查看。


如果您希望它与复选框的工作方式类似,则需要做一些工作才能使其正确。由于绑定的工作方式以及它们的顺序依赖性如何导致问题,我有这段代码感觉有点脆弱。你可以试试这个,我只是不确定它有多强大。

为此,您需要一个 observable 来跟踪实际选择的单选按钮的实际更改。然后,您可以订阅该 observable 的更改以更新您选择的 observable。

ko.bindingHandlers.radiochecked = {
    init: function (element, valueAccessor, allBindingsAccessor) {
        // the checked binding depends on the element having an initial value
        // we need to allow bindings that potentially set it to be applied first
        setTimeout(function () {
            var options = ko.utils.unwrapObservable(valueAccessor());
            if (options.checked()) {
                options.selected(element.value);
            }
            options.selected.subscribe(function (newValue) {
                options.checked(newValue === element.value);
            });
            ko.applyBindingsToNode(element, { checked: options.selected });
        }, 0);
    }
};

然后将其绑定到您的单选按钮:

<input type="radio" data-bind="
    value: id,
    radiochecked: { 
        'checked': chosen,
        'selected': $root.attributeValues2.selected
    },
    attr: { name: 'test2' }" />

演示

于 2012-11-16T23:52:37.850 回答
1

这也可能有所帮助。下面的绑定将采用一组单选按钮,在更改其中一个按钮时,将组中所有其他按钮后面的可观察对象设置为特定值(null、false、0、...)

就目前而言,它要求可观察对象的值是真/假,以便它选择正确的单选按钮。

ko.bindingHandlers.checkedRadio = {
    init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
        $(element).change(function () {
            //Get all radio buttons int he group
            var group = $(element).attr('name');
            var radios = $('input[type="radio"][name="' + group + '"]').not($(element));

            //Reset all values for other radio buttons in this group
            $.each(radios, function (i, radio) {
                var $r = $(radio);
                if (!$r.prop('checked')) {
                    var data = ko.dataFor(radio);
                    data[allBindingsAccessor().checkedRadioProperty](allBindingsAccessor().checkedRadioValue);
                }
            });

            //Update bound data
            var value = valueAccessor();
            var checked = $(element).prop('checked');
            value(checked);
        });

        //Select radio button based on bound data
        var value = unwrap(valueAccessor());
        $(element).prop('checked', value);
    }
};

要使用绑定,您可以:

<input type="radio" value="true" data-bind="name: 'option-group-' + attributeID() }, checkedRadio: chosen, checkedRadioProperty: 'chosen', checkedRadioValue: false" />
于 2012-11-19T18:58:57.247 回答