0

When I dynamically add a new element, I want to apply some function to it. For example, to turn regular <input> into date-time selector (via some plugin) I need to

$('.dt').dateTime();

The function above only works the first time I add elements during initialization. Whenever I add them later using .append() the function is not applied. For event listeners I use $(document).on() instead:

$(document).on('click', '.dt', function () {});

and it works in any case.

What is the equivalent to use on creation?

On SO I've seen solutions to similar problems that either use function .live() which is now deprecated, or use some sort of plugin which I don't want.

Is there any solution in plain jquery?

Praveen Kumar Purushothaman
  • 164,888
  • 24
  • 203
  • 252
xaxa
  • 1,057
  • 1
  • 24
  • 53
  • Could you create the element, call the plugin function and then append it? Rather than just appending straight away? e.g var $dt = $(''); $dt.dataTime(); $('body').append($dt); – TommyBs Jun 18 '15 at 11:53
  • Maybe plugin handles delegation. Can you provide link to plugin and maybe a jsFiddle?! – A. Wolff Jun 18 '15 at 12:03
  • jQuery is only aware of the elements in the page at the time that it runs, so new elements added to the DOM are unrecognized by jQuery. To combat that use [event delegation](http://learn.jquery.com/events/event-delegation/), bubbling events from newly added items up to a point in the DOM that was there when jQuery ran on page load. Many people use `document` as the place to catch the bubbled event, but it isn't necessary to go that high up the DOM tree. Ideally [you should delegate to the nearest parent that exists at the time of page load.](http://stackoverflow.com/a/12824698/1011527) – Jay Blanchard Jun 18 '15 at 12:32

5 Answers5

2

It is not possible to listen to element creation in jquery.

In order to initialize something on adding the element to the DOM you have several options:

  1. Use MutationObserver https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver however it doesn't have the best support out there.

  2. Manually initialize the plugin after appending an element (best bet).

vxsx
  • 448
  • 5
  • 12
0

According to .live() documentation you can use

Rewriting the .live() method in terms of its successors is straightforward; these are templates for equivalent calls for all three event attachment methods:

$( selector ).live( events, data, handler );                // jQuery 1.3+
$( document ).delegate( selector, events, data, handler );  // jQuery 1.4.3+
$( document ).on( events, selector, data, handler );        // jQuery 1.7+

I try it in jsfiddle and when you set .on function on parent element all elements inside (also in future) will have this event attached

$( ".main" ).on('click', '.cl', function() { alert('clicked'); });

$(".add").click(function() { 
   $( ".main" ).append( "<p class='cl'>Test</p>" );
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="add">Add</div>
<div class="main">
    <p class='cl'>1</p>
    <p>2</p>
    <p class='cl'>3</p>
    <p>4</p>
</div>
suvroc
  • 3,058
  • 1
  • 15
  • 29
  • 2
    This doesn't answer the question. – ttzn Jun 18 '15 at 12:02
  • I understood that @xaxa want to set click callback to each DOM elements: already created and this created dynamically. I think that it may solve this problem – suvroc Jun 18 '15 at 12:05
  • @suvroc what is the `event` equal to in my case? (on creation of a element) – xaxa Jun 18 '15 at 12:08
  • Actually it looks like your `$(document).on('click', '.dt', function () {});` from answer – suvroc Jun 18 '15 at 12:16
  • He doesn't want to add a click event, his click event example was explaining that he wants to bind a plugin similar to how you would bind a click event using 'on'. The plugin doesn't fire on click, it should just apply to the element when it is appended. – TommyBs Jun 18 '15 at 13:53
0

One other solution (other regarding @vxsx's answer and depending plugin behaviour) could be to use a delegated event, eg, mouseenter and initialize plugin using it, e.g:

$(document).on('mouseenter', '.dt:not(.dt_initiliazed)', function () {
    $(this).addClass('dt_initiliazed').dateTime();
});

One other solution would be to set a fake CSS animation/transition on specific elements .dt and use relevant event animationEnd/transitionEnd to initialize plugin. This would work even for elements added later in the DOM.

A. Wolff
  • 74,033
  • 9
  • 94
  • 155
0

On some modern browsers with jQuery you can try :

$(document).on('DOMNodeInserted', '.dt', function(event) {
    $(event.currentTarget).dateTime();
});

This feature is actually deprecated, so I advise you to follow vxsx's answer and either use the MutationObserver facility or, better yet, apply the function manually every time you append a .dt element. It shouldn't require more code than actually setting up an event listener.

ttzn
  • 2,543
  • 22
  • 26
0

You can use MutationObserver to detect new DOM element and force binding on these new items.

You can read this : http://gabrieleromanato.name/jquery-detecting-new-elements-with-the-mutationobserver-object/

Romain V...
  • 423
  • 2
  • 10