Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mustache JS, How to create a recursive list with an unknown number of sub lists?

I have seen this discussed in a few threads and it looked like this was (or is) the way to do this. But I can't seem to get this to work. So I must be missing something.

Output Should Look Like

<ul>
  <li>parent
     <ul> 
       <li>
          sub child
          <ul>
            <li> sub sub child</li>
          </ul>
       </li>
     </ul>
  </li>
</ul>

What I get is

<ul>
  <li>parent
     <ul> 
       <li>
          sub child
       </li>
     </ul>
  </li>
</ul>

What I have so far


template

<script type="text/template" id="template">
    <ul class="parent">
        {{#menu}}
        <li>
         {{item}}
         <ul class="popupmenu">
            {{#menu}}
           <li>{{item}}</li>
           {{/menu}}
        </ul>            
        </li>
        {{/menu}}
    </ul>
</script>

js

var data = {
    menu : [{
        "item" : "parent",
        "menu" : [{
            "item": "sub child",
            "menu": [{
                "item" : "sub sub child"  
            }]
         }]
    }]
};

var template = $("#template").html();

var rendered = Mustache.render(template, data);
$("body").html(rendered);

Fiddle

https://jsfiddle.net/6g7wz5vL/22/

Anyways, I thought mustache would recursively create the sub lists based off of the initial template. But it seems I have to create the entire nested HTML structure to get it to generate the HTML for the next levels.

So do I have to do a template for each level? What am I missing that I only get the first sub level and not the second? Or is this just not possible with Mustache?

like image 358
Kris Hollenbeck Avatar asked Aug 07 '15 19:08

Kris Hollenbeck


1 Answers

What you are missing is that the rendering of this type of menu has to be recursive. So you need to reference the template inside the template itself. Luckily mustache has this capability via the partials construct. So you can write something as follows:

var rendered = Mustache.render(template, data, {
    "recurse": "<ul class=\"submenu\">{{#menu}}<li>{{item}}{{>recurse}}{{/menu}}</ul>"
});

However because Mustache will always go up the hierarchy of nodes in the object graph, it will always find a "menu" element to render, so this will cause an infinite loop with your data. So an additional change to your data is necessary like so:

var data = {
    menu : [{
        "item" : "parent",
        "menu" : [{
            "item": "sub child",
            "menu": [{
                "item" : "sub sub child",
                "menu": null
            }]
         }]
    }]
};

Note the extra "menu": null line here. This will cause Mustache to terminate the recursion when it sees this.

I have updated the fiddle with these changes: https://jsfiddle.net/6g7wz5vL/24/.

like image 175
syazdani Avatar answered Oct 23 '22 00:10

syazdani