I had a similar issue last week when trying to bind events to a list of "things". My philosophical struggles lead me to this answer concerning the logic-less nature of Mustache (and Handlebars): https://stackoverflow.com/a/4946409/365252
It's important to note that Mustache is - by design - logic-less. What this is trying to accomplish is to aggravate motivate developers into separating logic from presentation, i.e anything that makes your presentation markup "dance" or link to "things" which is not expressible with markup alone should stay the hell away from your templates.
But back to our problem... the true Eureka moment came to me upon the realisation that my problem wasn't "How do I bind this with markup".
My true problem was: "There's clearly logic involved between the loop and the items of the loop. Why am I using Mustache to iterate over them in a logic-less environment?"
So after beating around the bush for a couple minutes, you might be wondering what my solution was:
This is my fictional template:
<h1>Argh these pesky topics!</h1>
{{{#topics}}} <!-- Note the 3 mustaches to avoid html escaping -->
And this is my row template:
<button>Shiver me timber, I'm rusty ol' {{name}}</button>
And then all the logic with ye olde Javascript:
/* Important: Assuming you're using jQuery, if not you'll have to convert the render output from a string to a DOM Node first. jQuery is NOT necessary for this to work - I'm just trying to avoid innerHTML hacks */
var topics = [/* whatever topics are,*/],
topicsDOM = document.createDocumentFragment(),
$ = jQuery,
list,
i, t, row;
for (i = 0, t = topics.length; i < t; i++) {
row = $(Mustache.render(yourRowTemplate, topics[i]));
row.on('click', function () {
/* We know exactly what row this is via topics[i] so you can do anything you'd like here */
};
topicsDOM.appendChild(row);
}
/* Now... this bit I'm not very proud of and I'm hoping someone can point out a better solution */
list = $(Mustache.render(yourListTemplate, {
topics: '<ins class="no-collision-please">'}));
/* We're doing this because we want to preserve the decorated DOM Nodes,
Mustache expects plain markup as a string (our <ins>) */
list.find('ins.no-collision-please').replaceWith(topicsDOM);
/* Note that the <ins> never leaves our little sandbox nor does
it cause reflow/layouting since we're working inside a documentFragment (list) */
return list;
And finally after swallowing all this Kool-Aid, the obvious aftertaste: I have to do THAT to bind an event, I'd rather just put a <script>
tag inside my template!?
If you have asked yourself this question, maybe logic-less templating isn't for you.
Disclaimer: I have been using Handlebars/Mustache for less than a month and I still find myself asking the question above for certain use cases. It's not a Silver Bullet.