我有复选框和单选按钮的相同数据结构。选中复选框时,它们会返回正确的布尔值('selected'变量)。
然而,当我检查单选按钮时,'selected'总是变为'value'(整数)。
即使'selected'== 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/
你能否解释一下这种行为以及为什么单选按钮不会更新布尔值(如复选框那样)?
答案 0 :(得分:5)
复选框和单选按钮的行为彼此不同。当单个observable绑定到checked
绑定(而不是数组)时,它们的行为特别不同。
对于复选框,它将始终是一个布尔值,指示是否已选中它。简单。如果是数组,则会在数组中添加/删除value
。
但是对于单选按钮,它将是分配给单选按钮的值。对于单个observable,只会考虑检查它绑定的值是否等于该值。在您的情况下,您的值绑定到id
,因此只有在chosen
值等于相应的id时才会响应。对于数组,它将向数组添加/删除值。
由于没有其他任何内容会改变相应属性chosen
的值,因此它保持不变
我调整了你的例子,以证明该值如何影响检查状态。 Updated fiddle
全部拼写in the documentation,仔细看看。
如果您希望它与复选框的工作方式类似,则需要一些工作才能使其正确。我有这个代码,由于绑定如何工作以及它们的顺序依赖性如何导致问题,感觉有点脆弱。你可以尝试一下,我只是不确定这是多么强大。
为此,您需要一个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' }" />
答案 1 :(得分:1)
这也可能有所帮助。下面的绑定将采用一组单选按钮,在更改其中一个时,将组中所有其余部分后面的observable设置为特定值(null,false,0,...)
就目前而言,它要求observable的值为true / false,以便选择正确的单选按钮。
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" />