I'm trying to do some complex binding with knockout (at least for a newbie like me).
Consider the following data:
var originalData = {
id: 1,
name: "Main",
children: [ { id: 2, name: "bob", children: []}, { id: 3, name: "ted", children: [{id: 5, name:"albert"}, {id: 9, name: "fred"}]} ],
selectedChild: { id: 2, name: "bob" }
};
<table>
<tr>
<td data-bind="text: name"></td>
</tr>
<tr data-bind="if: children().length > 0">
<td>
<select data-bind="options: children,
optionsText: function(item){
return item.name;
},
optionsCaption: 'Choose...'"></select>
</td>
</tr>
Ok, that was the easy part.
The hard part, is that whenever an item is selected in the list, if this item has children then a new select box should appear underneath. Its datasource would be the children of the selected item in the first select box. Of course, it could continue on with any level of deepness.
How should I solve this problem with knockout ?
I've put together a sample of what I have so far on jsfiddle: http://jsfiddle.net/graphicsxp/qXZjM/
You can use recursive templates in knockout by putting the template into a script
tag. Templates in a script
tag can reference themselves, like this:
<div data-bind="template: 'personTemplate'"></div>
<script type="text/ko" id="personTemplate">
<span data-bind="text: name"></span>
<select data-bind="options: children, optionsText: 'name', optionsCaption: 'Choose', value: selectedChild"></select>
<!-- ko if: selectedChild -->
<div data-bind="template: { name: 'personTemplate', data: selectedChild }"></div>
<!-- /ko -->
</script>
Here is the fiddle
Update:
You can use a computed
to easily do this, and remove the logic from the view (which I think is better in this case), and then bind the if
to it.
self.showChildren = ko.computed(function() {
return self.selectedChild()
&& self.selectedChild().children().length > 0;
});
If you want to put both in the if
block, you can, you just need to include the parens. The reason for this is that observables are functions; knockout lets you exclude them if you are just using the single reference, but they are required to "drill down" to their properties.
if: selectedChild() && selectedChild().children().length > 0
Here is the updated fiddle
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With