Event Delegation

One listener on a parent handles events from many current and future children by checking which child the event came from.

one click listener for the whole listhandle child clicks from the parentbuttons I add later do not respondstop attaching a listener to every single rowfigure out which row was clickedone listener instead of a thousandevent deligationthe old jQuery .on('click', '.row') trick

See it

Live demo coming soon

What it is

Most DOM events bubble from the element where they started through its ancestors. Event delegation uses that path in reverse: put one listener on a stable parent, inspect event.target, and handle the matching child. jQuery made the pattern familiar through delegated .on() handlers.

Reach for it on long or changing lists, tables, menus, and grids. New children work without registering new listeners because the parent was already listening. event.target is where the event began; event.currentTarget is the parent whose listener is running.

Gotcha: the target may be an icon or span inside the button, so match with closest() and confirm the result still belongs to the listening container. stopPropagation can cut off the path, and focus and blur do not bubble like focusin and focusout. Events crossing a shadow root may also be retargeted.

Ask AI for it

Replace the per-row click listeners in this dynamic list with one delegated click listener on the list element. Find the actionable child with event.target.closest('[data-action]'), verify it is contained by event.currentTarget, and dispatch from its data-action and data-id attributes. Keep real button elements for keyboard access, do not rely on stopPropagation, and remove the parent listener with the same function reference during cleanup. Explain the difference between event.target and event.currentTarget in the finished code.

You might have meant

side effectcomponentprogressive enhancementmodal dialoghook

Go deeper