jQuery selector doesn’t update after dynamically adding new elements

Depending upon what jQuery version you are using, you should use either .delegate() (before jQuery 1.7) or .on() (jQuery 1.7+) to have delegated event handling that will handle events for elements that are added dynamically. Note .live() has been deprecated from all versions of jQuery so it should no longer be used.

Using .on(), you can use this:

$("#attendance").on("keydown", "input:last", function(e) {
    if (e.which == 9) {
        var $this = $(this);
        var num = parseInt($this.attr('name').match(/\d+(,\d+)?/)[0]) + 1;
        $this.parent().append('<input type="text" name="attendance[' + num +']" value="Name and Position" class="medium" />');
    }
});

Using .delegate() would be similar (except the arguments are in a different order). You can see both of them in the jQuery doc .delegate() and .on().

Delegated event handling works using the “bubbling” capability of some javascript events. This allows you to attach an event handler to a parent object (that does not come and go) and have it look at each event that “bubbles” up to it from a child, check to see if the event comes from an object with an appropriate selector, and if so, execute your event handling code. This way, as objects come and go, their events are still handled appropriately.

As you were originally doing things, you would bind the event handler directly to the object that matched the selector 'section#attendance input:last' at the time the event binding code ran. From then on, it was bound directly to that specific object regardless of whether that object still matches the selector or if new objects are added to the DOM that would match the selector. Delegated event handling using .delegate() or .on() allows the event handling behavior to be more dynamic – automatically adjusting to changes in the DOM. You just have to bind the event to a common parent object that will not be changing and it can automatically monitor all it’s children.

Leave a Comment