jQuery .delegate() Method

Beginner
7 min read
Updated: Oct 2026
5 examples
Live preview

What Is .delegate()?

.delegate(selector, eventType, handler) attaches a handler on a root element for events from matching descendants — including elements added later (since 1.4.2). Argument order differs from .on().

Remember
// Deprecated (3.0+) — selector first
$("table").delegate("td", "click", function () {
  $(this).toggleClass("chosen");
});

// Modern equivalent — events first (1.7+)
$("table").on("click", "td", function () {
  $(this).toggleClass("chosen");
});
NeedUse
New delegated handlers.on(events, selector, handler)
Legacy delegated handlers.delegate(selector, events, handler)
Remove delegated handlers.undelegate() or .off()
Old document-wide live binding.live() (removed 1.9)
Fire a custom event.trigger()

How to Use .delegate()

Bind once on a stable parent; filter by child selector when the event bubbles up.

  1. Pick a root that will stay in the DOM (list, table, form, or body).
  2. Call .delegate(selector, eventType, handler) on that root.
  3. Inside the handler, this is the matched descendant that triggered the event.
  4. Add or remove matching children later — no rebind needed.
  5. In new code, write the same idea with .on(eventType, selector, handler).
PieceRequired?Role
selectorYesFilter which descendants may trigger the handler
eventType / eventsYesEvent name(s), or a map of events → handlers (1.4.3+)
eventDataOptionalData passed to the handler via event.data
handlerYes*Function to run (*not needed when using an events map)

Pseudocode

Pseudocode
attach listener on ROOT for EVENT

when EVENT bubbles to ROOT:
    find original target
    if target matches SELECTOR (or is inside a match):
        run HANDLER with this = matched element
    else:
        ignore

new children that match SELECTOR:
    work automatically — no extra bind

Cheat Sheet

Keep these mappings handy while reading legacy code.

TopicDetail
ReturnsjQuery (chainable)
Since1.4.2 · events map 1.4.3
DeprecatedjQuery 3.0 → use .on()
Migrate.delegate(sel, ev, fn) → .on(ev, sel, fn)
Remove.undelegate() / modern .off()
thisMatched descendant (not the root)
PropagationstopPropagation() below the root can block the handler

Live Preview

One .delegate() on the list — new items stay clickable.

Click any list item below — then add items and click those too.

Log
Ready — click an item or run an action.

jQuery Examples

Short, copy-ready snippets. Prefer rewriting these with .on() in new projects.

Example 1 — Dynamic Children

Click a paragraph to append another — new ones stay clickable.

jQuery
$("body").delegate("p", "click", function () {
  $(this).after("

Another paragraph!

"); });
Try It Yourself

How It Works

  1. Bind. One handler on body for clicks from p.
  2. Match. jQuery checks the bubbled target against "p".
  3. Act. this is the clicked paragraph; append a sibling.
  4. Future. New paragraphs match the same selector automatically.

Example 2 — Migrate to .on()

Same behavior — modern parameter order.

jQuery
// Legacy
$("table").delegate("td", "click", function () {
  $(this).text("clicked");
});

// Preferred (1.7+)
$("table").on("click", "td", function () {
  $(this).text("clicked");
});
Try It Yourself

How It Works

  1. Legacy. Selector comes before the event name.
  2. Modern. Event name comes first; selector is second.
  3. Same root. Still bind on table, not each td.
  4. Prefer. Use .on() so tooling and docs match current jQuery.

Example 3 — Event Data

Pass extra data into the handler the same way as .on().

jQuery
$("#list").delegate("button", "click", { source: "toolbar" }, function (event) {
  $("#out").text(
    $(this).text() + " · " + event.data.source
  );
});
Try It Yourself

How It Works

  1. Pass. The third argument is plain data for the handler.
  2. Read. Access it as event.data.
  3. Scope. Useful when one handler serves several roles.
  4. Modern. Same idea: .on("click", "button", data, fn).

Example 4 — Cancel Default Action

Stop a link’s navigation while still using delegation.

jQuery
$("#nav").delegate("a", "click", function (event) {
  event.preventDefault();
  $("#out").text("Opened: " + $(this).text());
});

// Or cancel default + bubbling:
// return false;
Try It Yourself

How It Works

  1. Delegate. Listen for a clicks under #nav.
  2. Prevent. preventDefault() blocks the browser navigation.
  3. Handle. Update the UI instead of following the href.
  4. Note. return false also stops bubbling; preventDefault alone does not.

Example 5 — Custom Event

Delegation works for custom event names too.

jQuery
$("body").delegate("p", "myCustomEvent", function (e, myName) {
  $(this).text("Hi there! " + myName);
});

$("#fire").on("click", function () {
  $("p").trigger("myCustomEvent", ["Sam"]);
});
Try It Yourself

How It Works

  1. Name. Register a handler for myCustomEvent on matching p elements.
  2. Trigger. .trigger() fires that event on each paragraph.
  3. Args. Extra trigger data arrives as handler arguments after event.
  4. Update. The paragraph text changes without a native DOM event.

Edge Cases & Pitfalls

Watch for these when reading or migrating delegated code.

order

Argument order vs .on()

.delegate(sel, ev, fn) vs .on(ev, sel, fn) — swapping casually causes silent bugs.

bubble

StopPropagation below the root

Handlers closer to the target can call stopPropagation() or return false and block the delegated handler.

root

Root must stay in the DOM

If you replace the parent you bound on, the delegated listener is gone — rebind or choose a higher stable root.

deprecated

jQuery Migrate may warn

With Migrate loaded, .delegate() calls often log deprecation warnings — treat them as a migration checklist.

Browser Support

.delegate() has been available since jQuery 1.4.2 and is deprecated since 3.0 (still present for compatibility). Prefer .on() for new work.

✓ Deprecated · jQuery 1.4.2+

.delegate()

Works wherever your loaded jQuery version includes it. New code should use .on(events, selector, handler) instead.

Legacy Use .on() instead
Google Chrome All versions · Desktop & Mobile
Full support
Mozilla Firefox All versions · Desktop & Mobile
Full support
Apple Safari All versions · macOS & iOS
Full support
Microsoft Edge All versions · Chromium & Legacy
Full support
Internet Explorer IE 6+ · Legacy environments
Full support
Opera All modern versions
Full support
.delegate() Deprecated

Bottom line: Still functional for legacy apps. Migrate to .on() / .off() when you touch the code.

Performance Notes

ApproachCostBest for
One delegated handler on a close rootLowLists, tables, dynamic UI
Many direct binds on each childHigherAvoid when children come and go
Delegating from document for everythingOK, but broaderPrefer a closer stable parent when possible

Delegation is usually cheaper than rebinding every new child. Keep the root as close as practical so fewer unrelated bubbles are filtered.

Key Takeaways

  • Role: one parent handler for matching children, including future ones.
  • Status: deprecated since 3.0 — use .on(events, selector, handler).
  • Migrate: swap selector/event order when converting to .on().
  • Remove: .undelegate() historically; prefer .off() today.

One line: .delegate() is legacy event delegation — learn it to read old code, write new code with .on().

Frequently Asked Questions

.delegate(selector, eventType, handler) attaches a handler on a root element for events from matching descendants — now or added later. One parent listener covers many children.
Yes. As of jQuery 3.0, .delegate() is deprecated. Prefer .on(events, selector, handler) since jQuery 1.7. The method still works for legacy code, but new projects should not use it.
Swap argument order: $(root).delegate(selector, events, data, handler) becomes $(root).on(events, selector, data, handler). Example: $('table').delegate('td', 'click', fn) → $('table').on('click', 'td', fn).
.live() always delegated from the document and could not choose a closer root. .delegate() lets you pick the parent (table, list, form). .live() was removed in 1.9; .delegate() was superseded by .on() and deprecated in 3.0.
You bind once on a stable parent instead of many handlers on each child. New elements added later still work without rebinding, and memory use stays lower on long lists.
Use .undelegate() for handlers attached with .delegate(), or migrate to .on() / .off(). Prefer .off(events, selector, handler) in modern code.

Next: .undelegate()

See how to remove handlers attached with .delegate().

.undelegate() tutorial →

About the author

Mari Selvan M P
Mari Selvan M P 🔗

Developer, cloud engineer, and technical writer

  • Experience 12 years building web and cloud systems
  • Focus Full Stack Development, AWS, and Developer Education

I write practical tutorials so students and working developers can learn by doing—from databases and APIs to deployment on AWS.

8 people found this page helpful