In Mustache, How to get the index of the current Section
I am using Mustache and using the data
{ "names": [ {"name":"John"}, {"name":"Mary"} ] }
My mustache template is:
{{#names}}
{{name}}
{{/names}}
What I want to be able to do is to get an index of the current number in the array. Something like:
{{#names}}
{{name}} is {{index}}
{{/names}}
and have it print out
John is 1
Mary is 2
Is it possible to get this with Mustache? or with Handlebars or another extension?
Solution 1:
This is how I do it in JavaScript:
var idx = 0;
var data = {
"names": [
{"name":"John"},
{"name":"Mary"}
],
"idx": function() {
return idx++;
}
};
var html = Mustache.render(template, data);
Your template:
{{#names}}
{{name}} is {{idx}}
{{/names}}
Solution 2:
For reference, this functionality is now built in to Handlebars which has compatibility with Mustache.
Use {{@index}}
{{#names}}
{{name}} is {{@index}}
{{/names}}
John is 0
Mary is 1
Solution 3:
In handlebars.js you can accomplish this with a helper function. (In fact, one of the advantages mentioned about handlebars here http://yehudakatz.com/2010/09/09/announcing-handlebars-js/ is that you can use helpers instead of having to rewrite the objects before calling the template.
So, you could do this:
var nameIndex = 0;
Handlebars.registerHelper('name_with_index', function() {
nameIndex++;
return this.name + " is " + nameIndex;
})
And, then your template can be this:
{{#names}}
<li>{{name_with_index}}</li>
{{/names}}
Your data is the same as before, i.e.:
{ "names": [ {"name":"John"}, {"name":"Mary"} ] };
And you get this output:
<li>John is 1</li>
<li>Mary is 2</li>
To make this really work, nameIndex needs to get reset each time the template is rendered, so to do that you can have a reset helper at the beginning of the list. So full code looks like this:
var data = { "names": [ {"name":"John"}, {"name":"Mary"} ] };
var templateSource = "<ul>{{reset_index}}{{#names}}<li>{{name_with_index}}</li>{{/names}}</ul>";
var template = Handlebars.compile(templateSource);
var helpers = function() {
var nameIndex = 0;
Handlebars.registerHelper('name_with_index', function() {
nameIndex++;
return this.name + " is " + nameIndex;
});
Handlebars.registerHelper('reset_index', function() {
nameIndex = 0;
})
}();
var htmlResult= template(data);
$('#target').html(htmlResult);
var htmlResult2= template(data);
$('#target2').html(htmlResult2);
(This can correctly render the template twice.)