Why don’t my event handlers fire for dynamically-added elements?
TL/DR: Because event handlers can only be bound to elements which exist in the DOM at the time you add them.
I hear this question asked often enough that it seemed worth documenting.
For dynamically-added elements, the event handler must be added to a parent object which exists in the page before the event handler code is called. That can be as vague as the page body, or something more specific when known, and pass it a selector matching your dynamic object.
Event handlers are bound only to the currently selected elements; they must exist on the page at the time your code makes the call to .on().
From the jQuery $.on() documentation
Each time an event occurs on an element, it bubbles up through the DOM tree (unless you tell it not to) . If the parent detects that the event originated from the specified child, and there's a handler set for this type of event, then the action is triggered. This is called delegated event handling.
I wondered if delegating the event to the body element rather than something more specific would cause performance issues; basically it depends on which event you're detecting. The jQuery $.on() documentation cautions as follows:
In most cases, an event such as click occurs infrequently and performance is not a significant concern. However, high frequency events such as mousemove or scroll can fire dozens of times per second, and in those cases it becomes more important to use events judiciously. Performance can be increased by reducing the amount of work done in the handler itself, caching information needed by the handler rather than recalculating it, or by rate-limiting the number of actual page updates using setTimeout.
Attaching many delegated event handlers near the top of the document tree can degrade performance. Each time the event occurs, jQuery must compare all selectors of all attached events of that type to every element in the path from the event target up to the top of the document. For best performance, attach delegated events at a document location as close as possible to the target elements. Avoid excessive use of document or document.body for delegated events on large documents.
~ Andy Westmoreland, Frontend Developer