Joseph Sjoblom Joseph Sjoblom - 11 months ago 86
jQuery Question

Knockout Json Nested Children - Changing Select Menu to Radio/Checkboxes

I have a working version of knockout code in which I'm using a parent select menu to determine what the child values should be.

Here's the example:

What I'm attempting to do is turn the parent level to a radios and the child level to checkboxes.

Here's what I've tried:

function ViewModel(items) {
this.levelOne = ko.observableArray(items);
this.selectedLevelOne = ko.observable();
this.selectedLevelTwo = ko.observable();

function getById(items, value) {
if(!value) {
return [];

var result = ko.utils.arrayFirst(items, function(item) {
return item.value === value;

return result && result.childItems || [];

this.levelTwo = ko.computed(function(){
var items = this.levelOne();
var id = this.selectedLevelOne()
return getById(items, id);
}, this);


var items = [
{text: "Marvel Superhero", value: "1", childItems: [
{text: 'Captain America', value: '01'},
{text: 'Ironman', value: '02'},
{text: 'Wolverine', value: '03'},
{text: 'Nightcrawler', value: '04'},
{text: 'Spiderman', value: '05'},
{text: 'Hulk', value: '06'},
{text: 'Thor', value: '07'},
{text: 'Hawkeye', value: '08'},
{text: 'Silver Surfer', value: '09'},
{text: 'The Thing', value: '10'},
{text: 'Mr Fantastic', value: '11'}
{text: "Marvel Villian", value: "2", childItems: [
{text: 'Dr. Doom', value: '01'},
{text: 'Magneto', value: '02'},
{text: 'Juggernaut', value: '03'},
{text: 'The Blob', value: '04'},
{text: 'Galactus', value: '05'}
{text: "DC Superhero", value: "3", childItems: [
{text: 'Superman', value: '01'},
{text: 'Batman', value: '02'},
{text: 'Robin', value: '03'},
{text: 'Wonder Woman', value: '04'},
{text: 'Raven', value: '05'},
{text: 'Aquaman', value: '06'}
{text: "DC Villian", value: "4", childItems: [
{text: 'Lex Luthor', value: '01'},
{text: 'Joker', value: '02'},
{text: 'Grundy', value: '03'},
{text: 'The Riddler', value: '04'},
{text: 'Lobo', value: '05'}

var module = {};

module.sampleViewModel = new ViewModel(items);

ko.applyBindings(module.sampleViewModel, document.getElementById("override-more"));

Does anyone have any advice on converting from select to radio/checkbox?

Is there a better way to do what I'm attempting?

Answer Source

When using foreach bindings, you are creating a new binding context (you might also have heard it called "scope"). You need to make sure to use $parent or $root when stepping back up.

You have a binding for radios that looks like this

<input type="radio" name="firstLevel" data-bind="checkedValue: value, checked: selectedLevelOne">

The problem is selectedLevelOne is on the parent. You can fix this binding like this:

<input type="radio" name="firstLevel" data-bind="checkedValue: value, checked: $parent.selectedLevelOne">

That will solve the radio buttons. The checkboxes are a different issue, since you are asking for multiple selections. Here, you can use the array-binding behavior of the checked binding

<input type="checkbox" name="nextLevel" data-bind="checked: $parent.selectedLevelTwo, checkedValue: $data">

Here is a working fiddle, showing the radio button selection, and checkboxes populating an array.

One problem is that when the parent radio is changed, the child selection array wont automatically updated. One way to solve this is with a subscription (this is in the fiddle).

this.selectedLevelOne.subscribe(function(newValue) {