2013-03-20 17 views
5

Ich versuche, einige komplexe Bindung mit Knockout (zumindest für einen Neuling wie mich) zu tun.knockout.js rekursive Bindung

Betrachten Sie die folgenden Daten:

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, dass der einfache Teil war.

Der schwierige Teil ist, dass, wenn ein Element in der Liste ausgewählt ist, wenn dieses Element Kinder hat, ein neues Auswahlfeld darunter angezeigt werden sollte. Seine Datenquelle wären die Kinder des ausgewählten Elements in der ersten Auswahlbox. Natürlich könnte es mit jeder Tiefe weitergehen.

Wie soll ich dieses Problem mit Knockout lösen?

Ich habe eine Probe zusammen, was ich habe bisher auf jsfiddle: http://jsfiddle.net/graphicsxp/qXZjM/

+0

ist eine, die mir in den Sinn kommt, ist eine Vorlage mit derselben Auswahlbox innen zu verwenden und die Vorlage an das Tabellenelement anhängen, wenn ein Element mit Kindern ausgewählt. Es ist noch nicht klar, wie ich es machen werde, aber denkst du, dass ich auf dem richtigen Weg bin? – Sam

Antwort

9

Sie rekursive Vorlagen in Knockout verwenden, können durch die Vorlage in einen script Tag setzen. Vorlagen in einem script Tag kann sich, wie diese Referenz:

<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> 

Hier the fiddle ist


Update:

Sie ein computed dies leicht tun können, und entfernen Sie die Logik aus der Sicht (was ich denke, ist in diesem Fall besser), und binden Sie dann die if daran.

self.showChildren = ko.computed(function() { 
    return self.selectedChild() 
     && self.selectedChild().children().length > 0; 
}); 

Wenn Sie sowohl im if Block setzen möchten, können Sie, müssen Sie nur die Pars aufzunehmen. Der Grund dafür ist, dass Observables Funktionen sind; Mit knockout können Sie sie ausschließen, wenn Sie nur die einzelne Referenz verwenden, aber sie müssen ihre Eigenschaften "aufschlüsseln".

if: selectedChild() && selectedChild().children().length > 0 

Hier ist die Idee updated fiddle

+0

Vielen Dank, das sieht super aus! Es ist ziemlich genau das, was ich brauche. Nur eine Sache, ich kann es nicht mit dem Mapping-Plugin arbeiten, während Sie eine fest codierte Person-Funktion verwendet haben. Kannst du mich darauf hinweisen, was ich falsch mache? jsfiddle hier: http://jsfiddle.net/graphicsxp/qXZjM/ – Sam

+0

eigentlich ignorieren meinen Kommentar, es funktioniert jetzt. Ich musste nur selectedChild-Eigenschaften auf ko.observable() setzen. Danke vielmals ! – Sam

+0

eine letzte Frage: Wie würden Sie die if-Bindung ändern, so dass die Vorlage nur anzeigt, ob es für das selectedChild mindestens ein Kind gibt? Ich habe ko versucht, wenn: selectedChild && selectedChild.children.length> 0 aber das funktioniert nicht .... Irgendeine Idee? – Sam