knockout.js - Knockout recursive template selective binding -


in example, i've got nested template display tree-view indented output, rendered html on leaf nodes not expect. how leaf nodes render expected html , not contain child container div?

if put if binding outside template binding, javascript error:

uncaught error: multiple bindings (if , template) trying control descendant bindings of same element. cannot use these bindings on same element.

note: using if binding comment <!-- ko if: children().length > 0 --> work remove unwanted element, resulting html riddled comments , i'd prefer keep clean have potentially hundreds of leaf nodes.

i've tried using 2 templates, 1 container , 1 without, , putting in condition name, template rendered nodetempl: data-bind="template: { name: (children().length > 0) ? 'nodetempl' : 'leaftempl', foreach: children }"

i guess want apply different template based on state of child it's processing.

a leaf node rendering this

<div>     <div data-bind="text: name">node 1-1-1</div>                 <div class="indent-1" data-bind="template: {if: children().length &gt; 0,  name: 'nodetempl', foreach: children }"></div> </div> 

but want render this:

<div>     <div data-bind="text: name">node 1-1-1</div>             </div> 

here's setup:

html

<style type="text/css">     .indent-1 {         margin-left: 20px;     } </style>  <script id="nodetempl" type="text/html">     <div>         <div data-bind="text: name"></div>                     <div class="indent-1" data-bind="template: {if: children().length > 0,  name: 'nodetempl', foreach: children }"></div>     </div> </script>  <div data-bind="template: { name: 'nodetempl', foreach: children }"></div>     

script

var node = function (config) {     var self = this;     self.name = ko.observable(config.name);     self.children = ko.observablearray([]);     if ($.isarray(config.children)) {         (var = 0; < config.children.length; i++) {             self.children.push(new node(config.children[i]));         }     } };  ko.applybindings(new node(     {         name: 'root',         children: [             { name: 'node1', children: [{name: 'node 1-1', children: [{name: 'node 1-1-1'}]},{name: 'node 1-2'}]},             {name: 'node2',children: [{name: 'node 2-1'},{name: 'node 2-2'}]},             {name: 'node3'},         ]     }     )); 

output

<div data-bind="template: { name: 'nodetempl', foreach: children }">     <div>         <div data-bind="text: name">node1</div>                     <div class="indent-1" data-bind="template: {if: children().length &gt; 0,  name: 'nodetempl', foreach: children }">     <div>         <div data-bind="text: name">node 1-1</div>                     <div class="indent-1" data-bind="template: {if: children().length &gt; 0,  name: 'nodetempl', foreach: children }">     <div>         <div data-bind="text: name">node 1-1-1</div>                     <div class="indent-1" data-bind="template: {if: children().length &gt; 0,  name: 'nodetempl', foreach: children }"></div>     </div> </div>     </div>      <div>         <div data-bind="text: name">node 1-2</div>                     <div class="indent-1" data-bind="template: {if: children().length &gt; 0,  name: 'nodetempl', foreach: children }"></div>     </div> </div>     </div>      <div>         <div data-bind="text: name">node2</div>                     <div class="indent-1" data-bind="template: {if: children().length &gt; 0,  name: 'nodetempl', foreach: children }">     <div>         <div data-bind="text: name">node 2-1</div>                     <div class="indent-1" data-bind="template: {if: children().length &gt; 0,  name: 'nodetempl', foreach: children }"></div>     </div>      <div>         <div data-bind="text: name">node 2-2</div>                     <div class="indent-1" data-bind="template: {if: children().length &gt; 0,  name: 'nodetempl', foreach: children }"></div>     </div> </div>     </div>      <div>         <div data-bind="text: name">node3</div>                     <div class="indent-1" data-bind="template: {if: children().length &gt; 0,  name: 'nodetempl', foreach: children }"></div>     </div> </div> 

you're on right track suggesting need 2 templates. template name parameter can function returns template name each item in array.

you can create function this:

function nodetemplate(node) {     return node.children().length > 0 ? 'nodetempl' : 'nodeleaftempl'; } 

and change view this:

<script id="nodetempl" type="text/html">     <div>         <div data-bind="text: name"></div>                     <div class="indent-1" data-bind="template: {name: nodetemplate, foreach: children }"></div>     </div> </script>  <script id="nodeleaftempl" type="text/html">     <div>         <div data-bind="text: name"></div>                 </div> </script>  <div data-bind="template: { name: nodetemplate, foreach: children }"></div>  

Comments

Popular posts from this blog

c# - Send Image in Json : 400 Bad request -

jquery - Fancybox - apply a function to several elements -

An easy way to program an Android keyboard layout app -