I have run into a strange issue when using Knockout to represent a parent/child relationship in my view model as a radio button selection in my view.
In the example below, I have a view model that represents two Applications. Each Application contains three Roles and a Selected Role Id.
In the view, I display the Roles under each Application as a list of radio buttons. The button whose value matches the parent’s Selected Role Id should be checked.
<script src='knockout-2.0.0.js' type='text/javascript'></script>
<script src='knockout.mapping.js' type='text/javascript'></script>
<ul data-bind='template: { name: "applicationTemplate", foreach: Applications }'></ul>
<script type='text/html' id='applicationTemplate'>
<li><span data-bind='text: Name'></li>
<ul data-bind='template: { name: "roleTemplate", foreach: Roles }'></ul>
</script>
<script type='text/html' id='roleTemplate'>
<li>
<input type='radio' data-bind='value: Id,
checked: $parent.SelectedRoleId(),
attr: { name: "roleFor" + $parent.Id(), id: "roleFor" + $parent.Id() + "_" + Id() }' />
<label data-bind='text: Name,
attr: { for: "roleFor" + $parent.Id() + "_" + Id() }'></label>
</li>
</script>
<script type='text/javascript' language='javascript'>
var data = {
'Applications': [
{ 'Id': 8, 'Name': 'Weather Predictor', 'SelectedRoleId': 1, 'Roles': [
{ 'Id': 1, 'Name': 'Meteorologist' },
{ 'Id': 2, 'Name': 'Farmer' },
{ 'Id': 3, 'Name': 'Pair of Dice' }
]
},
{ 'Id': 9, 'Name': 'Daily Crime Report', 'SelectedRoleId': 6, 'Roles': [
{ 'Id': 4, 'Name': 'Superhero' },
{ 'Id': 5, 'Name': 'Commissioner' },
{ 'Id': 6, 'Name': 'Journalist' }
]
}
]
};
var viewModel = ko.mapping.fromJS(data);
ko.applyBindings(viewModel);
</script>
Everything renders fine at first:
- Weather Predictor
- [X] Meteorologist
- [ ] Farmer
- [ ] Pair of Dice
- Daily Crime Report
- [ ] Superhero
- [ ] Commissioner
- [X] Journalist
But when I click on “Farmer”, all of the Roles under “Weather Predictor” appear unchecked:
- Weather Predictor
- [ ] Meteorologist
- [ ] Farmer
- [ ] Pair of Dice
- Daily Crime Report
- [ ] Superhero
- [ ] Commissioner
- [X] Journalist
Clicking “Farmer” a second time will not only check the radio button, but it will function properly from then on. It’s only the first click that acts buggy. The same problem will happen if I click on “Pair of Dice”, as well, or any other unchecked radio button for that matter.
This problem has been perplexing me for a while, and I’m beginning to wonder if I’m using Knockout improperly here.
Any insight into this issue would be greatly appreciated!
When you are using the
checkedbinding, you would want to avoid using thevaluebinding with it, as it will attach unnecessary event handlers.An easy option is to add the
valuein yourattrbinding (so you are just setting the value attribute and not adding event handlers) and then put thecheckedbinding after it (so thevalueis already set beforecheckedruns) like:Sample: http://jsfiddle.net/rniemeyer/Y478G/