jQuery won't bind click to underscore template using .on() for items added via function

javascript, jquery, underscore.js

Solution

Instead of binding events directly to the elements, bind one event to their container element, and delegate it:

$("#divID").on("click", ".pickup", function () {
    // Your event handler code
});

DEMO: http://jsfiddle.net/3GvPX/3/

In this case, the event handler is only executed for elements inside of the container `#divID` that have the class "pickup".

And in your scenario, the elements are being added to the element with an `id` of "divID". Thus, where the two selectors came from.

This is handy because, as you've found out, dynamically adding elements doesn't magically bind event handlers; event handlers bound normally with `.on()` are only executed (bound) on those present at the time of binding.

It could even help if you change the delegated selector to `"span.pickup"` (if you know the elements will always be a `<span>` like in your template), so that the DOM is filtered by the tag name first.

Reference:

- http://api.jquery.com/on/#direct-and-delegated-events

Problem

I'm using underscore to create some elements and appending them to a div with jQuery. At the bottom of the page I'm using jQuery's `.on()` to respond to clicks on the elements. ``` $('.pickup').on('click', function(e) { alert("hello"); } ); ``` Via some user interaction (in Google maps), I've got to add more elements to the div and want them to respond to clicks as well. For some reason they do not. I've pared it all down on jsfiddle: http://jsfiddle.net/thunderrabbit/3GvPX/ When the page loads, note that clicking on the lines in output will `alert('hello')` via jQuery. But click the [add] button and the new lines do not respond to clicks. My HTML ``` <div id="unit_2225" class="pickup"> <span>Click me; I was here first</span> </div> <script type="text/template" id="unit-template"> <div class="unit-item"> <span class="pickup"> <span>click us (<%= unit_id %>) via underscore</span> </span> </div> </script> <div id="divID"> </div> <button>add</button> ``` My Javascript ``` var addUnitToDiv = function(key,val) { console.log(val); var template = _.template($('#unit-template').html(),val); $('#divID').append(template); } var unit_ids = [{unit_id:'hello'}, {unit_id:'click'}, {unit_id:'us'}, {unit_id:'too'}, {unit_id:112}]; $.each(unit_ids, addUnitToDiv); var unit_pids = [{unit_id:'we'}, {unit_id:'wont'}, {unit_id:'respond'}, {unit_id:'to'}, {unit_id:'clicks'}, {unit_id:358}]; createMore = function() { $.each(unit_pids, addUnitToDiv); } $('.pickup').on('click','span',function() { alert("hello"); }); $('button').click(createMore); ``` I found a similarly worded question but couldn't figure out how to apply its answer here.

Original source