I have the same data structure for checkboxes and radio buttons. When checking the checkboxes, they return correct boolean value (‘chosen’ variable).
However, when I check the radio buttons, ‘chosen’ always changes to the ‘value’ (integer).
Also the radio buttons don’t get “checked” in the beginning, even though ‘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>
Here is my fiddle: http://jsfiddle.net/SN7Vn/1/
Can you please explain this behavior and why the radio buttons don’t update boolean (like checkboxes do)?
Check boxes and Radio buttons behave differently from each other. When a single observable is bound to the
checkedbinding (as opposed to an array) is where they particularly behave differently.For a check box, it will always be a boolean value indicating whether it was checked or not. Simple. If an array, the
valuewill be added/removed from the array.However for a radio button, the it will be the value assigned to the radio button. For a single observable, it will only be considered checked the value of what it is bound to is equal to the value. In your case, your value is bound to the
idso will only respond if thechosenvalue is equal to the corresponding id. For an array, it will add/remove the value to the array.Since nothing else alters the value of the
chosenfor the corresponding attribute, it remains the sameI tweaked your example to demonstrate a bit how the value can affect the checked state. Updated fiddle
It’s all spelled out in the documentation, look at it closer.
If you want it to work similarly to how it does for checkboxes, it will take a bit of work to get it right. I have this code which feels a bit fragile due to how the bindings work and how their order dependentness can cause problems. You can try this out, I’m just not sure how robust this is.
For this to work, you’ll need an observable to keep track of the actual changes to what radio button is actually selected. Then you can subscribe to changes on that observable to update the observable of your choice.
Then bind it to your radio buttons:
Demo