22

I'm creating dynamically a couple of div with inner controls. Two of those controls should be datepickers. But for some reason they are not showing (only input text are shown) It works if I create static html, but not when I'm using dynamic one.

This is the code I'm using to generate the HTML (I can see the div)

var ShowContainerDiv = document.createElement('DIV');

var btnShowDiv = document.createElement('DIV');
btnShowDiv.id = 'btnShowDiv ';
btnShowDiv.title = 'Change';
btnShowDiv.index = 120;

var lblShow = document.createElement('label')
lblShow.htmlFor = "btnShowDiv";
lblShow.appendChild(document.createTextNode('Show'));
btnShowDiv.appendChild(lblShow );
btnShowDiv.onclick = function () {
    dropdown.style.visibility = "visible";
};

var dropdown = document.createElement('DIV');
dropdown.style.backgroundColor = 'white';
dropdown.style.borderStyle = 'solid';
dropdown.style.borderWidth = '2px';
dropdown.style.cursor = 'pointer';
dropdown.style.textAlign = 'left';
dropdown.style.width = '150px';

var chkRed = document.createElement("input");
chkRed.type = "checkbox";
chkRed.id = "chkRed";
chkRed.value = "Red";
chkRed.checked = false;
var lblRed = document.createElement('label')
lblRed.htmlFor = "chkRed";
lblRed.style.color = "#F00";
lblRed.appendChild(document.createTextNode('Red'));

var chkYellow = document.createElement("input");
chkYellow.type = "checkbox";
chkYellow.id = "chkYellow";
chkYellow.value = "Yellow";
chkYellow.checked = false;
var lblYellow = document.createElement('label')
lblYellow.htmlFor = "chkYellow";
lblYellow.style.color = "#FF0";
lblYellow.appendChild(document.createTextNode('Yellow'));

var chkGreen = document.createElement("input");
chkGreen.type = "checkbox";
chkGreen.id = "chkGreen";
chkGreen.value = "Green";
chkGreen.checked = false;
var lblGreen = document.createElement('label')
lblGreen.htmlFor = "chkGreen";
lblGreen.style.color = "#0F0";
lblGreen.appendChild(document.createTextNode('Green'));

var dateFrom = document.createElement("input");
dateFrom.id = "txtDateFrom";
dateFrom.type = "text";
dateFrom.className = "datepicker";
dateFrom.style.width = "70px";
dateFrom.readonly = "readonly";
var lblDateFrom = document.createElement('label')
lblDateFrom.htmlFor = "txtDateFrom";
lblDateFrom.appendChild(document.createTextNode('From'));

var dateTo = document.createElement("input");
dateTo.id = "txtDateTo";
dateTo.type = "text";
dateTo.className = "datepicker";
dateTo.style.width = "70px";
dateTo.readonly = "readonly";
var lblDateTo = document.createElement('label')
lblDateTo.htmlFor = "txtDateTo";
lblDateTo.appendChild(document.createTextNode('To'));

var btnDone = document.createElement("input");
btnDone.type = "button";
btnDone.name = "btnDone";
btnDone.value = "Done";
btnDone.onclick = function () {
    dropdown.style.visibility = "hidden";
};

dropdown.appendChild(chkRed);
dropdown.appendChild(lblRed);
dropdown.appendChild(document.createElement("BR"));
dropdown.appendChild(chkYellow);
dropdown.appendChild(lblYellow);
dropdown.appendChild(document.createElement("BR"));
dropdown.appendChild(chkGreen);
dropdown.appendChild(lblGreen);
dropdown.appendChild(document.createElement("BR"));
dropdown.appendChild(dateFrom);
dropdown.appendChild(document.createElement("BR"));
dropdown.appendChild(dateTo);
dropdown.appendChild(document.createElement("BR"));
dropdown.appendChild(btnDone);

ShowContainerDiv.appendChild(btnShowDiv);
ShowContainerDiv.appendChild(dropdown);

g.event.addDomListener(btnShowDiv, 'click', function () {
    dropdown.visible = true;
    dropdown.style.visibility = "visible";
});

g.event.addDomListener(btnDone, 'click', function () {
    dropdown.visible = false;
    dropdown.style.visibility = "hidden";
});

map.controls[g.ControlPosition.TOP_RIGHT].push(ShowContainerDiv);

Then in a .js file I have this (I checked and I'm including the file)

$(document).ready(function () {
    $(".datepicker").datepicker({
        dateFormat: 'yy/m/d',
        firstDay: 1,
        changeMonth: true,
        changeYear: true,
        showOn: 'both',
        autosize: true,
        buttonText: "Select date",
        buttonImage: '../Content/images/calendar.png',
        buttonImageOnly: true
    });
});

Why the datepicker is not showing up?

Dharman
  • 30,962
  • 25
  • 85
  • 135
polonskyg
  • 4,269
  • 9
  • 41
  • 93

10 Answers10

32

When you write

$(document).ready(function () {
    $(".datepicker").datepicker({...});
});

This fragment is getting executed right after the page has loaded. Therefore, your dynamic datepickers are not there yet. You need to call $(aSuitableSelector).datepicker(...) on each newly-inserted element. First, use a var to hold your options:

var datePickerOptions = {
    dateFormat: 'yy/m/d',
    firstDay: 1,
    changeMonth: true,
    changeYear: true,
    // ...
}

This allows you to write

 $(document).ready(function () {
    $(".datepicker").datepicker(datePickerOptions);
 });

and to write

 // right after appending dateFrom to the document ...
 $(dateFrom).datepicker(datePickerOptions);

 //...

 // right after appending dateTo ...
 $(dateTo).datepicker(datePickerOptions);

You can also use JQuery's ability to listen to DOM changes to avoid having to apply JS magic to newly-inserted elements -- but I do not think it is worth it.

Community
  • 1
  • 1
tucuxi
  • 17,561
  • 2
  • 43
  • 74
  • The devil is in the details! It works by using the created element as selector (as you show) instead of $("#id"). Will award bounty as soon as I can. – Fredrik Håård Aug 05 '12 at 12:26
  • 1
    actually, it would also work with `$(".datepicker")`... it's the placement, not the selector that is doing the magic. However, using the element as the selector avoids re-applying datepicker to other, perfectly valid datepickers. – tucuxi Aug 05 '12 at 12:48
  • 1
    Thanks for the answer, very useful ! However, can you change ".datePicker" to ".datepicker" in your last paragraph ? There is no capital p ("P") in the function name. It looks like an obvious syntax error but it took me a couple of minutes to figure out what "TypeError: $(...)datePicker is not a function" was about.. – user2154283 Aug 22 '13 at 01:13
  • Even by wrapping my piece of code into `$(window).load(function() {` ... or `$(document).ready(function() {` ... I still couldn't get my element with a selector (used $(""), find(), pseudo-classes, ids, nth-child, ...). The length of the result will always be 0. – Alex Mar 03 '15 at 13:49
  • @Alex - if you are dynamically adding a date field, selectors for that new field will not work *until after the field has been added*. – tucuxi Mar 03 '15 at 14:11
  • Believe me or not, but that dynamically added field can be accessed by the Id I gave to it. Pseudo-class selector won't work but by it's id it works. I can confirm that I tried to access it after the content was created (window loaded and document ready, I even put my selector on a function called with setInterval of 5000 ms). if someone know why it can only be accessed by it's id ... ty for reply – Alex Mar 03 '15 at 14:39
  • @Alex - post minimal code as question, with a "why does this happen". – tucuxi Mar 03 '15 at 19:01
  • @tucuxi thanks for the answer got a logic to do the same. – Smit Patel Dec 17 '15 at 06:06
13

The easiest way I found to add datepicker for dynamically added multiple input field:

    $('body').on('focus',".datepicker", function(){
        $(this).datepicker();
    });
dinesh regmi
  • 131
  • 1
  • 2
4

You can simply use this.

$('body').on('focus',".date-picker", function(){
  $(this).datepicker();
});
Naveen Kumar
  • 1,476
  • 5
  • 28
  • 52
2

The easiest way I found to fix this issue is by using the livequery plugin:

http://docs.jquery.com/Plugins/livequery

Instead of applying the datepickers to all objects of a specific class, you tell LiveQuery to apply it to those objects. LiveQuery will in turn keep applying the datepicker, even when your DOM is changed later on.

I have seen no performance drops when usnig this, and the code changes are really minimal (you need to add the plugin to the page and only change one line of code).

You would be using it like so:

$(".datepicker").livequery(
        function(){ 
            // This function is called when a new object is found. 
            $(this).datepicker({ ...}});
        }, 
        function() { 
            // This function is called when an existing item is being removed. I don't think you need this one so just leave it as an empty function.
        }
); 

From then on, every time you add an object with the datepicker class, the datepicker plugin will automatically be applied to it.

Flater
  • 12,908
  • 4
  • 39
  • 62
  • Please note that as of jQuery 1.7, you can use the `.on()` method using a delegate event handler (http://api.jquery.com/on/). Livequery still works though, if you prefer it. – Flater Mar 18 '13 at 08:24
0

The code that bind the datepickers is best to be executed right after your html is dinamically created. If you want to keep the code for datepicker initialization in a separate file, I would recommend the following approach: After you finish generating your html (I presume it is generated on document ready), use

$(document).trigger("customHtmlGenerated");

And in the datepicker file, instead of $(document).ready(function(){...}) use $(document).bind("customHtmlGenerated", function(){...});

FreeCandies
  • 1,088
  • 10
  • 21
0

I put the

$( "#InstallDate" ).datepicker({
  showOn: "button",
    minDate: 0, // no past dates
  buttonImage: "../images/Date.png",
  buttonImageOnly: true,
  buttonText: "Select date",
  dateFormat: 'yy-mm-dd',
}); 

into a script file DatePicker.js and then added the following line at the end of my generated Ajax Html form

<script type='text/javascript' src='/inc/DatePicker.js'></script> 
zzapper
  • 4,743
  • 5
  • 48
  • 45
0
$( ".datepicker" ).datepicker({inline: true,dateFormat: "dd-mm-yy"});
Vipin Yadav
  • 707
  • 5
  • 6
0

Please add below code after appending element.

$(".datepicker").datepicker({
        dateFormat: 'yy/m/d',
        firstDay: 1,
        changeMonth: true,
        changeYear: true,
        showOn: 'both',
        autosize: true,
        buttonText: "Select date",
        buttonImage: '../Content/images/calendar.png',
        buttonImageOnly: true
    });
Community
  • 1
  • 1
-1

The jQuery code is executed when the document is ready: this means when the initial markup of your page is ready, not after your javascript files ran.

I suppose your code to initialize the datepickers runs before your script creating the elements does, so nothing happens.


Try executing you jquery code when the page has loaded using .load() instead of .ready(). The load event is fired when all assets (js, image...) have loaded.

$(window).load(function () {
    $(".datepicker").datepicker({
        ...
    });
});

You could also simply use the way javascript is executed. Scripts are executed in the order they happen in the page. So you could:

  • move your scripts right before the closing body tag ```
  • make sure your first script (creating the elements) comes before the datepicker code
  • remove the .ready() handler for the date picker. When you place your script at the end, they are implicitly running when the DOM is ready...
Community
  • 1
  • 1
Didier Ghys
  • 30,396
  • 9
  • 75
  • 81
  • 1
    The same happens. I tried this: (init is the function that creates the html) window.onload = function () { init(true); $(".datepicker").datepicker({... – polonskyg Mar 09 '12 at 22:10
-1

It's probably a matter of in which order the javascript is being fired. Try putting

$(".datepicker").datepicker({
    dateFormat: 'yy/m/d',
    firstDay: 1,
    changeMonth: true,
    changeYear: true,
    showOn: 'both',
    autosize: true,
    buttonText: "Select date",
    buttonImage: '../Content/images/calendar.png',
    buttonImageOnly: true
});

After your javascript that creates the html.

Caleb Doucet
  • 1,751
  • 2
  • 14
  • 29