knockout.js recursive binding

…衆ロ難τιáo~ 提交于 2020-01-02 04:51:26

问题


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/


回答1:


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



来源:https://stackoverflow.com/questions/15531670/knockout-js-recursive-binding

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!