Delegation & Event Namespaces

Scale event handling with delegation and keep it tidy with namespaced events.

You already met basic delegation: $(parent).on("click", "child", fn). As an app grows, two advanced habits keep your event layer sane.

Namespaces — label your handlers

Add a .something suffix to an event name and you can later remove just your handlers without disturbing anyone else's:

$(document).on("click.myWidget", "button", handler);
$(window).on("resize.myWidget", onResize);

// Later, tear down everything this widget attached β€” and nothing else:
$(document).off(".myWidget");
$(window).off(".myWidget");

This is how well-behaved widgets clean up after themselves. Without namespaces, $(document).off("click") would nuke every click handler on the page.

Delegation that survives re-rendering

Because the listener lives on a stable ancestor, delegated handlers keep working when you replace the inner HTML wholesale — the classic pain point of “my buttons stopped working after I reloaded the list.”

ApproachHandles future elements?Number of listeners
Direct bind on each childNoOne per child
Delegated on parentYesOne, total

Inside a delegated handler, this is the matched child, while event.target is the exact element clicked (which may be a descendant of it).

Example

Try it yourself
Loading editor…
Press Run to see the result.

When to use it

  • A single-page application attaches one delegated handler per route to a static shell div, covering all dynamic content injected later.
  • A plugin removes only its own handlers on teardown using .off('.pluginName') without disturbing other listeners on the element.
  • A drag-and-drop widget attaches mousedown.dnd, mousemove.dnd, and mouseup.dnd so they can all be removed cleanly as a group.

More examples

Delegated click on dynamic rows

The delegated handler on tbody with the .gridSelect namespace covers all future rows and can be removed cleanly later.

Example Β· html
<table id="grid"><tbody></tbody></table>
<button id="addRow">Add row</button>
<p id="sel"></p>
<script>
$(function () {
  var n = 0;
  $("#addRow").click(function () {
    n++;
    $("#grid tbody").append("<tr><td>Row " + n + "</td></tr>");
  });
  $("#grid tbody").on("click.gridSelect", "tr", function () {
    $("tr").removeClass("selected");
    $(this).addClass("selected");
    $("#sel").text($(this).find("td").text());
  });
});
</script>

Remove only namespaced handler

.off("click.feature") removes only the namespaced handler, leaving any other click listeners on the element intact.

Example Β· html
<div id="box" style="padding:20px;background:#eee;">Box</div>
<button id="add">Add handler</button>
<button id="remove">Remove handler</button>
<script>
$(function () {
  $("#add").click(function () {
    $("#box").on("click.feature", function () {
      alert("Feature handler fired!");
    });
  });
  $("#remove").click(function () {
    $("#box").off("click.feature"); // removes only this handler
  });
});
</script>

Grouped handlers for drag behaviour

All drag-related handlers share the .drag namespace so mousemove.drag can be removed on mouseup without a stored reference.

Example Β· html
<div id="draggable" style="width:60px;height:60px;background:#3498db;position:absolute;cursor:grab;"></div>
<script>
$(function () {
  var offsetX, offsetY;
  $("#draggable")
    .on("mousedown.drag", function (e) {
      offsetX = e.pageX - $(this).offset().left;
      offsetY = e.pageY - $(this).offset().top;
      $(document).on("mousemove.drag", function (e) {
        $("#draggable").css({ left: e.pageX - offsetX, top: e.pageY - offsetY });
      });
    })
    .on("mouseup.drag", function () {
      $(document).off("mousemove.drag");
    });
});
</script>

Discussion

  • Be the first to comment on this lesson.
Delegation & Event Namespaces β€” jQuery | SoundsCode