I would like to use handlebars.js or mustache.js to iterate over a list of families, and then iterate over that family\'s members. Inside of both loops, I want to display pr
Great answer @maxbeatty.
I just wanted to add another example if anyone have the same problem and can't understand the above solution.
First I have one dimensional array which I wanted to split on every 4 elements:
// this is the one dimensional data we have from let's say a mysql query
var array = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', ...];
// think of it as [[], [], [], [], [], ...]
// but instead we'll be adding a dummy object with a dummyKey
// since we need a key to iterate on
var jagged = [];
var size = 4, // this is the size of each block
total = array.length / block; // total count of all blocks
// slice the initial one dimensional array into blocks of 4 elements each
for (var i=0; i < total; i++) {
jagged.push({dummyKey: array.slice(i*size, (i+1)*size)});
}
Now if we pass jagged
into our view we can iterate it like that:
<ul>
{{#jagged}}
<li>
<ul>
{{#dummyKey}}
<li>{{.}}</li>
{{/dummyKey}}
</ul>
</li>
{{/jagged}}
</ul>
If we have our initial array filled with objects:
var array = [{key1: 'a',
key2: 'b'},
{key1: 'c',
key2: 'd'},
{key1: 'e',
key2: 'f'},
...
];
Then in our template we'll have:
<ul>
{{#jagged}}
<li>
<ul>
{{#dummyKey}}
<li>{{key1}} - {{key2}}</li>
{{/dummyKey}}
</ul>
</li>
{{/jagged}}
</ul>
For a dataset like below:
{
rows:
["1A", "1B"],
["2A", "2B"],
["3A", "3B"]
}
following will work in mustachejs:
<tbody>
{{#rows}}
<tr>
{{#.}}
<td>{{.}}</td>
{{/.}}
</tr>
{{/rows}}
</tbody>
I was looking for the same issue using mustache and the answers were given for handlebars, and the ones for mustache required extra JS, I know it is old but I'll add my working example just in case somebody else needs it. Cheers!
JSON:
"experience": [
{
"company": "Company 1",
"position": "Graphic Designer",
"tasks": ["Task 1", "Task 2", "Task 3"]
},
{
"company": "Company 2",
"position": "Graphic Designer",
"tasks": ["Task 1", "Task 2", "Task 3", "Task 4", "Task 5"]
}
]
TEMPLATE:
{{#experience}}
<h2>{{company}}</h2>
<div class="position">{{position}}</div>
<div class="occupazione">Responsabilities</div>
<ul>
{{#tasks}}
<li>{{.}}</li>
{{/tasks}}
</ul>
{{/experience}}
You can reference the parent loop variable and index with the ../
operator:
{{#each families}}
{{#each this.members}}
<p>Current member: {{ this.name }} (this = inner loop itterator)</p>
<p>Current family: {{ ../this.title }} (../this = parent loop itterator)</p>
<p>Current member index: {{ @index }}</p>
<p>Current family index: {{ @../index }}</p>
{{/each}}
{{/each}}
You can nest sections easily with lists of objects. Use a data structure where families
is a list that has an object members
that has a list of any objects (or even more lists)like:
{
"families" : [
{
"surname": "Jones",
"members": [
{"given": "Jim"},
{"given": "John"},
{"given": "Jill"}
]
},
{
"surname": "Smith",
"members": [
{"given": "Steve"},
{"given": "Sally"}
]
}
]
}
You would be able to populate a template like:
<ul>
{{#families}}
<li>{{surname}}
<ul>
{{#members}}
<li>{{given}}</li>
{{/members}}
</ul>
</li>
{{/families}}
</ul>
jsFiddle is currently down so here's the full working HTML with JS:
<!DOCTYPE html>
<head>
<script src="http://cdnjs.cloudflare.com/ajax/libs/mustache.js/0.3.0/mustache.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script>
$(function() {
var tpl = $('#fam').html(),
data = {
"families" : [
{
"surname": "Jones",
"members": [
{"given": "Jim"},
{"given": "John"},
{"given": "Jill"}
]
},
{
"surname": "Smith",
"members": [
{"given": "Steve"},
{"given": "Sally"}
]
}
]
},
html = Mustache.to_html(tpl, data);
$("#main").append(html);
});
</script>
</head>
<div id="main"></div>
<script type="template/text" id="fam">
<ul>
{{#families}}
<li>{{surname}}
<ul>
{{#members}}
<li>{{given}}</li>
{{/members}}
</ul>
</li>
{{/families}}
</ul>
</script>
Sorry I'm a little late in the game here. The accepted answer is great but I wanted to add an answer that I think is also useful, especially if you are iterating over simple row/column arrays.
When you're working with nested handlebar paths, you can use ../
to refer to the parent template context (see here for more information).
So for your example, you could do:
{{#each families}}
{{#each members}}
<p>{{../surname}}</p>
<p>{{given}}</p>
{{/each}}
{{/each}}
This was especially useful for me because I was making a grid and I wanted to give each square a class name corresponding to its row and column position. So if rows
and columns
, simply return arrays, I can do this:
<tbody>
{{#each rows}}
<tr>
{{#each columns}}
<td class="{{this}}{{../this}}"></td>
{{/each}}
</tr>
{{/each}}
</tbody>
Update
This solution is for Handlebars. A comment below explains why it will not work in Mustache.