jQuery on load of dynamic element
Asked Answered
L

2

38

I'm trying to do some conditional manipulation of elements that are dynamically added to some container on a page, but I'm missing an event.

Say I have a container:

<div id="container"></div>

I can easily bind an event handler to the click function for all new elements, using

$('#container').on('click', '.sub-element', function() { ... });

But what do I bind to in order to get a "one-time" hook when the element is added to #container. I have tried to bind to ready and load to no avail. Is there any way to do this, or do I have to come up with another solution to my problem?

This fiddle contains my non-working example.

Lazar answered 7/3, 2012 at 22:41 Comment(5)
In all browsers, the load event does not bubble. In Internet Explorer 8 and lower, the paste and reset events do not bubble. Such events are not supported for use with delegation, but they can be used when the event handler is directly attached to the element generating the event. (api.jquery.com/on) Now, as for how to work around that...Melodramatize
Would it be an issue to remove the 'load' functionality you're trying to accomplish all together, and instead manipulate the html after the item has appended by 'chaining'? $('#container').append('<div class="sub-element">No worky!</div>').html('<b>yaay!</b>');Ela
@Ela it's not that I can't come up with a work-around (and more so for this silly example), I just want to know if there is an event I have missed that can be used for the purpose I'm describing.Lazar
@Melodramatize The load event only fires on elements that have a URL associated with them, like an image, or a style-sheet.Akan
I actually started to write to that in my comment but figured since you can't delegate on load anyway, it didn't matter. Good to include though, I suppose.Melodramatize
A
43

You can trigger a custom event on the newly added DOM element that can be picked-up by a jQuery event handler:

//bind to our custom event for the `.sub-element` elements
$('#container').on('custom-update', '.sub-element', function(){
    $(this).html('<b>yaay!</b>');
});

//append a new element to the container,
//then select it, based on the knowledge that it is the last child of the container element,
//and then trigger our custom event on the element
$('#container').append('<div class="sub-element">No worky!</div>').children().last().trigger('custom-update');

Here is a demo: http://jsfiddle.net/ggHh7/4/

This method allows you to do something globally even if you load the dynamic content through different methods.

Update

I'm not sure of the browser support (I'll assume IE8 and older don't support this) but you can use the DOMNodeInserted mutation event to detect when a DOM element is added:

$('#container').on('DOMNodeInserted', '.sub-element', function(){
    $(this).html('<b>yaay!</b>');
})

$('#container').append('<div class="sub-element">No worky!</div>');

Here is a demo: http://jsfiddle.net/ggHh7/7/

UPDATE

There is a new API for this as DOMNodeInserted is depreciated at this time. I haven't looked into it but it's called MutationOvserver: https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver

Akan answered 7/3, 2012 at 22:55 Comment(6)
Interesting, +1, and all... so you are saying that there is no way I can be notified when some third-party plugIn adds an element to some container. If I'm not the one appending it, I'm screwed?Lazar
You can setup an interval that checks for new DOM elements every so often. Otherwise there are mutation events, DOMNodeInserted is probably what you want but the browser support may not be what you need: developer.mozilla.org/en/DOM_Client_Object_Cross-Reference/… (Look at the Mutation and mutation name event types section). See my update for an example of using DOMNodeInserted.Akan
You would need to use a method such as Long Polling to monitor the element for changes in length, if the length changes, then grab the difference in length. That will give you whatever 'object' resides there. It's unconventional, but it will work.Ela
Thanks a lot Jasper. I don't think that it solves my problem, with the compatibility issues and all, but it answers my question for sure. Thanks for your time.Lazar
DOMNodeInserted is deprecatedPostilion
@Postilion Thanks, I updated the answer with a link to the new API.Akan
V
10

After reading the above answer I now use this successfully:

$('body').on({
   DOMNodeInserted : function(){
      alert('I have been added dynamically');
   },
   click : function(){
      alert('I was clicked');
   },
   '.dynamicElements'
});

Now all my dynamicElements can do stuff as they're loaded, utilizing the awesome .on() event map.

Viipuri answered 3/3, 2013 at 1:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.