Problem with jQuery UI Datepicker and Copied Dynamic DOM: Solved

Today, I ran into an interesting problem with the jQuery UI Datepicker, for which I couldn’t find any assistance. In retrospect, it was a fairly simple issue but it took me quite awhile to debug. If I didn’t have Firebug, I don’t think it would’ve ever been solved this issue. I spent a great deal of time searching for solutions on Google but unfortunately nobody was able to help me solve my problem so I thought I would document this here for anyone else in the same shoes.

What I was up to:

I was trying to create a dynamic address section. I was using some simple jQuery to copy a section of code (.address_template) and then I was using jQuery to inject it into the document. The goal was to allow the user to add an unlimited number of previous addresses, each with a start and end date selectable using the jQuery UI datepicker.

The problem:
In my document, I was using jQuery to create instances of datepicker() for each instance of .address_date. This worked great for the single instance that appeared but failed miserably for elements added dynamically to the DOM after the page had loaded. I tried various solutions I found for similar problems other users had. Some of these included:

- Adding a unique ID to each instance of the datepicker.
- Using datepicker(“destroy”) then redeclaring datepicker()

#(‘address_template’).datepicker(‘destroy’).datepicker();

This technique works excellent if all of your elements were added properly to DOM but I discovered another but I wasn’t expecting.

What I was doing wrong:
I was copying the HTML after the datepicker(); had been initially added to the template. This means I was copying the HTML after the datepicker() function had modified it. Before I spent some time analyzing the HTML with Firebug I didn’t realize that the datepicker() function actually modifies the HTML adding in its own class .hasDatepicker.

When I copied the HTML I was copying the HTML after this class was added so the jQuery UI failed when trying to initiate a new datepicker(); and datepicker(“destroy”); failed because a true instance didn’t exist. I was caught in a real catch 22.

How I solved the problem:
I modified my code to reset the style of the .address_date class when I added it into the DOM prior to adding datepicker to that specific element. As soon as I did this it began to work sweet.

Below is an example of my code in case it is helpful to anyway. This one is really more about theory than exact code:

$('#addaddress').click(function() {
        var count = $('.address_template').size();
        var html = $('.address_template').eq(0).html();
        $('#addaddress').before('<div class="address_template">' + html + '</div>');
        $('.address_template H1').eq(count).html("Previous Address " + count);
        $('.address_date').eq(count).attr("class","address_date");
        $('.address_date').eq(count).attr("id","movein" + count);
        $("#movein" + count).datepicker();
});

Also here are the reference posts from stackoverflow that helped me reach my solution:
1. http://stackoverflow.com/questions/34790/duplicating-jquery-datepicker/1423156#1423156

2. http://stackoverflow.com/questions/1059107/why-does-jquery-uis-datepicker-break-with-a-dynamic-dom

No related posts.

If you enjoyed this post, please consider to leave a comment or subscribe to the feed and get future articles delivered to your feed reader.

Comments

Dude you saved my life. I was so stuck on this the other day and my client wouldn’t drop it so I searched again this morning and found your post. Great work.

Thanks, that saved me!

It doesn’t work for me. I get an error when method .datepicker(‘destroy’) is called. (Error: c is undefined)
I’m using jquery 1.4 and jquery ui 1.8.2

I was wondering why my cloned form fields weren’t showing the datepicker when I found this post. You helped me a lot, thanks!

http://blog.robertglynn.info/post/jQuery-datepicker-plugin-gotcha.aspx

@pixelcone it sounds like you may have a different problem. If you give some more detail we may be able to help out.

@Rob Glynn Glad to hear the post was helpful. Good article by the way.

wonderful post! was stuck for a while on this. saved me from much more troubleshooting. thanks!

Thank you! This was driving me insane.

I actually ended up just adding one line:

$(‘.datepicker’).attr(‘class’, ‘datepicker’);

before recalling $(‘.datepicker’).datepicker({ … });

…which is probably not the most efficient process as it’s reinitializing all of the datepickers rather than just the new ones, but it works fine and I can move on to more important things now.

Thanks again.

Here’s another way to do it:

$(“#TemplateDateElement”).datepicker(“destroy”); // Remove

// Do your clone and whatever dirty work you need to do,
// including adding your cloned element back into the page.
// Also be sure to init the datepicker for the cloned element.

$(“#TemplateDateElement”).datepicker( options ); // Reinstate

Got me around this issue. I had originally tried just cloning the element, destroying the “attached” datepicker and restoring it to the cloned element but the destroy ended up causing an error that made Firefox submit the form. Fun.

Your post reminded me that it was manipulating the underlying elements. The trick was making sure I destroyed the datepicker BEFORE I tried cloning it.

You have saved me too! Thanks!

Thanks. Saved me hours.

I did the same digging like you but have not imagined that .hasDatepicker class was the problem. Just solved by adding … .removeClass(‘hasDatepicker’).datepicker(…

I did the same digging like you but have not imagined that .hasDatepicker class was the problem. Just solved by adding … .removeClass(‘hasDatepicker’).datepicker(…

Thank you

Doesnt work. After selecting date in new clone field value of date is being set to original field!

Hi everyone,

I was having a similar issue. First of all I had to get rid of the clone method because it was too generic and it was better to re-cretea row by row and cell by cell.

Then, for the datepicker issue I re-defined it in the .js file after adding the element and it worked like a charm. This is how the part of the js looks like:

var txt = document.createElement(‘input’);
txt.type = ‘text’;
txt.name = ‘f_hasta[' + iteration + ']‘;
txt.id = ‘datepicker_fh_’ + iteration;
txt.size = 9;
txt.value = ”;
txt.readOnly = ‘readonly’;
cell5.appendChild(txt);

$(function(){
$(“#datepicker_fh_”+iteration).datepicker($.extend({},
$.datepicker.regional["es"], {
dateFormat: “d-M-y”,
firstDay: 7,
beforeShowDay: $.datepicker.noWeekends,
showStatus: true,
showAnim: “slideDown”,
duration: “slow”,
direction: “down”,
showOn: “button”,
buttonImage: “http://europa.staff.cema.edu.ar/crm/application/images/icons/ico_calendario.gif”,
autoSize: true,
buttonImageOnly: true,
changeMonth: true,
changeYear: true,
yearRange: ’1930:2050′
}));
}).attr(“readonly”, “readonly”);

var myBr = document.createElement(‘br’);
cell5.appendChild(myBr);

Hey, if you’re having the issue that after cloning element and setting datepicker always picks the selected date to the original element instead of the cloned one, you just have to strip your code, stop cloning the element, instead recreate it. like this:

$(‘.add_service_period’).click(function(){
$(”).appendTo(‘#service_period_div’);
var dates_from = $(”);
var dates_to = $(”);
dates_from.appendTo(‘#service_period_div’).datepicker(datepicker_opts);
dates_to.appendTo(‘#service_period_div’).datepicker(datepicker_opts);
});

the first $(“”) had a “br”, and the second ones had the inputs that i wanted to “clone” ;)

cheers!

Saved me! Thanks a bunch!

Yes! Thank you! I went with KenLG’s solution. Simply moved my destroy above the cloning bits and it works perfectly. Thanks all!

Leave a comment

(required)

(required)