127

I have dynamically created textboxes, and I want each of them to be able to display a calendar on click. The code I am using is:

$(".datepicker_recurring_start" ).datepicker();

Which will only work on the first textbox, even though all my textboxes have a class called datepicker_recurring_start.

Your help is much appreciated!

Very Curious
  • 881
  • 3
  • 26
  • 50
steeped
  • 2,613
  • 5
  • 27
  • 43
  • When you say "dynamically created", do you mean with code-behind before the page loads or with javascript after the page loading? Because if the elements are added after the page loading, you'll need to rebind the calendar each time a new textbox is added. – DangerMonkey May 03 '12 at 14:13
  • I am loading it in the code-behind with PHP. – steeped May 03 '12 at 14:27
  • I think you might be getting confused, but then its hard to tell with the info you've supplied. So just to confirm, can you confirm what you mean by 'dynamically created textboxes' please. – Tr1stan May 03 '12 at 14:31
  • If I am loading 'page one', php looks at the db to see how many date textboxes are in 'page one' and displays it. So when 'page one' loads, there will be 4 textboxes which need to load the datepicker(). 'page two' has 7 textboxes which need to load the datepicker() function. – steeped May 03 '12 at 14:38
  • If you have a problem with data picker not working after a first call, check out this answer: http://stackoverflow.com/a/16283547/1329910 Your problem may have to do with datepicker adding its own class: hasDatepicker – Vlad Apr 29 '13 at 16:43

13 Answers13

299

here is the trick:

$('body').on('focus',".datepicker_recurring_start", function(){
    $(this).datepicker();
});​

DEMO

The $('...selector..').on('..event..', '...another-selector...', ...callback...); syntax means:
Add a listener to ...selector.. (the body in our example) for the event ..event.. ('focus' in our example). For all the descendants of the matching nodes that matches the selector ...another-selector... (.datepicker_recurring_start in our example) , apply the event handler ...callback... (the inline function in our example)

See http://api.jquery.com/on/ and especially the section about "delegated events"

ilyes kooli
  • 11,959
  • 14
  • 50
  • 79
  • 4
    This is a solution that would work in any kind of dynamic appending. +1 to you. – DangerMonkey May 03 '12 at 14:32
  • 6
    Although it seems strange to me that you'd want to call `.datapicker()` every time the textbox gains focus - so you'd want to be careful with this approach (assuming I'm reading this right). However, I think you'd be OK with the `.datapicker()` because it will probably check if a datepicker is created before trying to recreate. With other code you might not have this grace. Also, .on( is only introduced in JQuery 1.7 - so make sure you're using the correct version. – Tr1stan May 03 '12 at 14:36
  • 3
    datepicker is clever enough to check if it is already created or not (all jQueryUI components by the way) if jQuery version is below 1.7 you can simply use **live** – ilyes kooli May 03 '12 at 14:42
  • @skafandri +1 - totally agree: however for a newbie, they might be tempted to use this design for other code which might not be so 'smart', which could quickly and exponentially eat-up your browser – Tr1stan May 03 '12 at 14:54
  • actually, I always use this design, (directly inspired from the **singleton design pattern** even in my hand coded plugins I use it, if the plugin is called, I check first if is the first time (I use the **data** jQuery function to store that information) – ilyes kooli May 03 '12 at 14:57
  • I don't see this as a problem, my answer is about **adding datepicker on dynamically created elements** not about **cloned elements**... – ilyes kooli Oct 25 '13 at 07:50
  • 7
    You might want to add a filter `:not(.hasDatepicker)` – Salman A Oct 31 '13 at 07:11
  • This is a simple and elegant solution. Exactly what I needed. +1 – Bob Roberts Nov 01 '13 at 14:44
  • worked for me.. and probably i can use the same method on other elements too.. :) – Ravi Kumar Gupta Nov 24 '13 at 04:43
  • +1 to you. I have been looking for this solution for a day already. Thank you! – Shawn Ang Jun 06 '14 at 00:59
  • in my case it is not working . i mean working with only the last element i have generated . mean if i have created 10 element it is working only with last element – Swarna Sekhar Dhar Apr 08 '16 at 13:08
  • It should work with all matched elements, can you post a demo to your non working script? – ilyes kooli Apr 11 '16 at 06:04
  • 1
    Beware of using jQuery.clone() within an area that includes a datepicker. If you do, add this to remove the hasDatepicker class AND the id datepicker adds to your input: .... find('input.hasDatepicker').removeClass('hasDatepicker').removeAttr('id'); – yahermann Jan 27 '17 at 05:35
  • @skafandri Thanks For the Help. Can We do this on Bootstrap Autocomplete? – always-a-learner Apr 29 '17 at 07:22
  • worked but it opens calender when jquery validation fails coz of focus. – Bugfixer May 24 '17 at 13:02
  • if you are looking for a solution on JQuery 1.3+ see my answer below, it also shows on the first click/focus – Mauricio Gracia Gutierrez Jan 11 '18 at 21:41
  • doen't it add multiple duplicate event handlers on same input – Vikas Kandari Oct 19 '19 at 10:44
  • @ilyeskooli what if the element is not an input type. I wanted to add the date picker to span element which created by dynamically. This focus and other events not supporting that – user2837480 Mar 23 '21 at 03:46
50

For me below jquery worked:

changing "body" to document

$(document).on('focus',".datepicker_recurring_start", function(){
    $(this).datepicker();
});

Thanks to skafandri

Note: make sure your id is different for each field

Community
  • 1
  • 1
Tapash
  • 762
  • 9
  • 7
  • Correct - for me I have to use $(document) and not $('body') - Sort of the problem with small snippets of code. I can get the example to work no problem, but and soon as I add in a bunch of my javascript into a fiddle this code no longer works for me. Thanks to both though. – Tom Stickel Jul 06 '15 at 23:41
19

Excellent answer by skafandri +1

This is just updated to check for hasDatepicker class.

$('body').on('focus',".datepicker", function(){

    if( $(this).hasClass('hasDatepicker') === false )  {
        $(this).datepicker();
    }

});
pleshy
  • 1,468
  • 2
  • 16
  • 22
  • 2
    Could that then be shortened to ```$('body').on('focus',".datepicker:not(.hasDatepicker)", function(){$(this).datepicker();});```? – Luke Stevenson Mar 14 '18 at 05:07
13

Make sure your element with the .date-picker class does NOT already have a hasDatepicker class. If it does, even an attempt to re-initialize with $myDatepicker.datepicker(); will fail! Instead you need to do...

$myDatepicker.removeClass('hasDatepicker').datepicker();
wintondeshong
  • 1,257
  • 15
  • 19
6

You need to run the .datepicker(); again after you've dynamically created the other textbox elements.

I would recommend doing so in the callback method of the call that is adding the elements to the DOM.

So lets say you're using the JQuery Load method to pull the elements from a source and load them into the DOM, you would do something like this:

$('#id_of_div_youre_dynamically_adding_to').load('ajax/get_textbox', function() {
  $(".datepicker_recurring_start" ).datepicker();
});
Tr1stan
  • 2,755
  • 1
  • 26
  • 45
  • 1
    This does not always work in practice from my experience. Best case is to add unique IDs to your elements and use those IDs to reference them and apply the datepicker. Seems internally the plugin uses those selectors. – Wes Johnson Jan 13 '15 at 20:57
2

This was what worked for me (using jquery datepicker):

$('body').on('focus', '.datepicker', function() {
 $(this).removeClass('hasDatepicker').datepicker();
});
1

The new method for dynamic elements is MutationsObserver .. The following example uses underscore.js to use ( _.each ) function.

MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver;    

var observerjQueryPlugins = new MutationObserver(function (repeaterWrapper) {

    _.each(repeaterWrapper, function (repeaterItem, index) {

        var jq_nodes = $(repeaterItem.addedNodes);

        jq_nodes.each(function () {

            // Date Picker
            $(this).parents('.current-repeateritem-container').find('.element-datepicker').datepicker({
                dateFormat: "dd MM, yy",
                showAnim: "slideDown",
                changeMonth: true,
                numberOfMonths: 1
            });

        });

    });

});

observerjQueryPlugins.observe(document, {
    childList: true,
    subtree: true,
    attributes: false,
    characterData: false
});
Hady Shaltout
  • 606
  • 1
  • 9
  • 22
1
 $('body').on('focus',".my_date_picker", function(){
            $(this).datepicker({
                minDate: new Date(),
            });
        });
kush
  • 595
  • 5
  • 7
0

None of the other solutions worked for me. In my app, I'm adding the date range elements to the document using jquery and then applying datepicker to them. So none of the event solutions worked for some reason.

This is what finally worked:

$(document).on('changeDate',"#elementid", function(){
    alert('event fired');
});

Hope this helps someone because this set me back a bit.

Chris
  • 893
  • 10
  • 23
0

you can add the class .datepicker in a javascript function, to be able to dynamically change the input type

 $("#ddlDefault").addClass("datepicker");
 $(".datepicker").datetimepicker({ timepicker: false, format: 'd/m/Y', });
Nada N. Hantouli
  • 1,310
  • 1
  • 12
  • 20
0

I have modified @skafandri answer to avoid re-apply the datepicker constructor to all inputs with .datepicker_recurring_start class.

Here's the HTML:

<div id="content"></div>
<button id="cmd">add a datepicker</button>

Here's the JS:

$('#cmd').click(function() {
  var new_datepicker = $('<input type="text">').datepicker();
  $('#content').append('<br>a datepicker ').append(new_datepicker);
});

here's a working demo

c0x6a
  • 427
  • 1
  • 6
  • 14
0

This is what worked for me on JQuery 1.3 and is showing on the first click/focus

function vincularDatePickers() {
    $('.mostrar_calendario').live('click', function () {
        $(this).datepicker({ showButtonPanel: true, changeMonth: true, changeYear: true, showOn: 'focus' }).focus();
    });
}

this needs that your input have the class 'mostrar_calendario'

Live is for JQuery 1.3+ for newer versions you need to adapt this to "on"

See more about the difference here http://api.jquery.com/live/

Mauricio Gracia Gutierrez
  • 10,288
  • 6
  • 68
  • 99
0
$( ".datepicker_recurring_start" ).each(function(){
    $(this).datepicker({
        dateFormat:"dd/mm/yy",
        yearRange: '2000:2012',
        changeYear: true,
        changeMonth: true
    });
});
Siya Matsakarn
  • 427
  • 4
  • 8