Reputation: 59231
I had code like this:
$('.remove-group').click(function () {
$(this).closest('tr').remove();
});
This worked fine until I needed to use delegated event handler to capture clicks for elements that will be added to the page in the future.
$(document).on('click', '.remove-group', function () {
$(this).closest('tr').remove();
});
This no longer works because the this
keyword does not refer to the originating element.
Any ideas?
It would seem that in my efforts to simplify the code for my question I actually made it work. I was actually passing in a wrapped set that was assigned to a variable instead of the string selector.
var $removeGroup = $('.remove-group');
$(document).on('click', $removeGroup, function () {
$(this).closest('tr').remove();
});
That doesn't seem to work when I do it that way.
Upvotes: 17
Views: 11493
Reputation: 543
Hope this helps someone:
$('#container').on('click', '.remove-group', function(event) {
$(this); // returns $('.remove-group') equivalent
$(event.target); // returns $('.remove-group') equivalent
$(event.delegateTarget); // returns $('#container') equivalent
});
Reference: http://api.jquery.com/event.delegateTarget/
I just want to clarify some of the mistakes I originally made.
It would seem the .on()
handler in jQuery has some specific usage that isn't clearly spelled out in the documentation.
You can use .on()
directly on the selector itself:
$('button').on('click', function () { $(this).css('border', 'solid 1px red'); });
It will work, but it will NOT apply to any future elements dynamically added to the page with the same selector. This is different from the way .live()
used to work. You must bind to the document object to catch future elements as well as current ones. This is because the selector is now the element you are listening on and it will catch all click events that bubble up to that element (document being one of the topmost elements to listen on). Then you pass the selector for the element you're interested in as a second argument after the event name.
$(document).on('click', 'button', function () { $(this).css('border', 'solid 1px red'); });
Now the listener will filter out click events until it finds one that was originally fired on 'button' and bubbled up to document.
You must supply a string selector, not a wrapped set. This will not work:
var $buttons = $('button');
$(document).on('click', $button, function () { $(this).css('border', 'solid 1px red'); });
For examples, see this jsbin.
Basically you just have to listen on a higher scope than the dynamic element. This makes sense considering that the dynamic elements you want to listen for are, by definition, being added/removed after your code runs and registers your event listener.
Upvotes: 31
Reputation: 18233
To get the "originating element for the event", you would use the target
property of the event object:
$(document).on('click', '.remove-group', function (e) {
$(e.target).closest('tr').remove();
});
However, that approach probably isn't what you actually want, since the originating element might actually be a descendant of .remove-group
whose 'click' event simply bubbled up the targeted element - meaning you might remove the wrong row in the event of a nested table. In the context of the .on()
handler, this
does in fact refer to the element matched by .remove-group
. To bind to a delegated event on this element using .on()
, the syntax is as follows:
$(static-parent-element).on(event, selector-string, handler)
For example, this is the correct syntax:
$(document).on('click', '.remove-group', function () {
$(this).closest('tr').remove();
});
This will match current and future .remove-group
elements, and remove the nearest tr
ancestor. You can (and should) replace document
here with the closest parent element of .remove-group
which exists in the DOM at the time of binding, and will still exist whenever this event is expected to be triggered (i.e. is static). Doing this minimizes the distance which the event has to bubble up the DOM tree before the event is triggered.
Upvotes: 10
Reputation: 94121
$(this)
should work fine but try event.target
in any case.
$(document).on('click', '.remove-group', function (event) {
$(event.target).closest('tr').remove();
});
Demo: http://jsbin.com/inewoc/1/edit
Upvotes: 1