Recommended Solution
My recommendation is to add an index
key
let data = {
"names": [
{"name": "John"},
{"name": "Mary"}
]
};
// Add an index manually
data = {
names: [
{ index: 0, name: "John" },
{ index: 1, name: "Mary" }
]
};
// Add an index with a loop
data = data.names.map((name, index) => name.index = index);
// Nested arrays with indices (parentIndex, childIndex)
data = {
names: [{
parentIndex: 0,
name: "John",
friends: [{
childIndex: 0,
name: "Mary"
}]
}]
};
Problems with proposed Mustache Index solutions
Other proposed solutions are not as clean, as detailed below...
@Index
Mustache does not support @Index
IndexOf
This solution runs in O(n^2) time, and therefore it does not have the best performance. Also the index must be manually created for each list.
const data = {
list: ['a', 'b', 'c'],
listIndex: function () {
return data.list.indexOf(this);
}
};
Mustache.render('{{#list}}{{listIndex}}{{/list}}', data);
Global Variable
This solution runs in O(n) time, so better performance here, but also "pollutes the global space" (i.e. adds properties to the window
object, and the memory is not freed by the garbage collector until the browser window closes), and the index must be manually created for each list.
const data = {
list: ['a', 'b', 'c'],
listIndex: function () {
return (++window.listIndex || (window.listIndex = 0));
}
};
Mustache.render('{{#list}}{{listIndex}}{{/list}}', data);
Local Variable
This solution runs in O(n) time, does not "pollute the global space", and does not need to be manually created for each list. However, the solution is complex and does not work well with nested lists.
const data = {
listA: ['a', 'b', 'c'],
index: () => name => (++data[`${name}Index`] || (data[`${name}Index`] = 0))
};
Mustache.render('{{#listA}}{{#index}}listA{{/index}}{{/listA}}', data);