我正在尝试与淘汰赛进行一些复杂的绑定(至少对于像我这样的新手)。
考虑以下数据:
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>
好的,这很容易。
困难的部分是,无论何时在列表中选择某个项目,如果此项目有子项,则下方会出现一个新的选择框。其数据源将是第一个选择框中所选项目的子项。当然,它可以继续保持任何深度。
我应该如何解决这个问题?
我在jsfiddle上汇总了我目前的样本:http://jsfiddle.net/graphicsxp/qXZjM/
答案 0 :(得分:9)
您可以将模板放入script
标记,以便在淘汰赛中使用递归模板。 script
标记中的模板可以引用自己,如下所示:
<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>
以下是the fiddle
更新
您可以使用computed
轻松执行此操作,并从视图中删除逻辑(在这种情况下我认为更好),然后将if
绑定到它。
self.showChildren = ko.computed(function() {
return self.selectedChild()
&& self.selectedChild().children().length > 0;
});
如果你想将两者放在if
区块中,你可以,你只需要包括parens。原因是可观察性是功能;如果您只是使用单个引用,则knockout允许您排除它们,但是它们需要“向下钻取”到它们的属性。
if: selectedChild() && selectedChild().children().length > 0