Wednesday, March 5, 2014

Recursive List Building With Handlebars

I always end up implementing some convoluted JavaScript inside a Handlebars helper whenever I have to render lists with any depth. Think trees — there could be several nested lists. I don't like the JavaScript approach I've taken in the past, I'm using Handlebars to generate dynamic markup — it should be able to handle nested lists, right? My preferred approach these days is to use a partial template, and to call that recursively.

Here's a fiddle that illustrates the concept. We have the following data that we want to render as a tree. Nested ul elements, in other words.

var items = [
    { name: "foo1" },
    { name: "foo2" },
    { name: "foo3", items: [
        { name: "foo4" },
        { name: "foo5" },
        { name: "foo6", items: [
            { name: "foo7" }    
        ]}
    ]},
    { name: "foo8" }
];

Here are the two Handlebars templates used to render the tree, one of which is a partial.

<script id="list" type="x-handlebars-template">
    {{#each items}}
    <li>
        {{name}}
        {{#if items}}
        <ul>
        {{> list}}
        </ul>
        {{/if}}
    </li>
    {{/each}}
</script>

<script id="main" type="x-handlebars-template">
    <ul>
    {{> list}}
    </ul>
</script>

You can see that the main template is just rendering the topmost ul element of the tree. Inside, it's rendering the partial template called list. It's this partial that does all the heavy lifting. The tree data we're passing to the template is an array of objects. Each object has a name property, and this what's rendered in the li element. The object may also have an items property. This is an array of child nodes, and the way the list partial deals with them is by recursively calling itself if the property is there.