Search code examples
javascriptevent-handlingdom-eventshandlebars.jstemplate-engine

How to bind events to html generated by templating/data binding engines (No Jquery)


When using a templeting engine such as Handlebars.js or a data binding one such as Rivets.js, content in the view is generated or updated based on changes in your model. That means that the content itself will lose any event listeners bound to it upon initial generation if the model ever changes.

I could go into the framework itself and customize it to add my specific listener to a specific type of content when it is generated, but this seems like a horrible idea in terms of maintainability and scale etc.

I could bind an event listener to the model object so that when it's changed new listeners are bound to the resulting view, but this seems like it would add a whole lot of overhead.

Or the cleanest way I have thought of is simply having the event listener as an attribute in the html template itself, invoking a globally accessible function.

<script id="foo-template" type="text/x-handlebars-template">
    <ul id="NumsSymbs">

        {{#each this}}
            <li onclick="globalFunction()"><a href="#">{{this}}</a></li>
        {{/each}}
    </ul>

</script>

This way whenever the template is re-rendered, or a single item in that list is re-rendered (if using rivets) the listener will be automatically in the rendered html.

My question is if however there is an even better way of doing this, perhaps a standard? How do MVC frameworks like Angular.js or Ember.js handle this sort of thing?


Solution

  • You can delegate in plain javascript as well, it's not really that hard, it just takes a little extra work

    document.getElementById('NumsSymbs').addEventListener('click', function(e) {
        var target = e.target, // the clicked element that the event bubbled from
            search = 'LI';     // element it needs to be inside
    
        do {
            if (target.nodeName.toUpperCase() === search) { // if match found
                globalFunction();
            }
        } while (target = target.parentNode); // iterate up through parents
    
    }, false);