129

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!

5
  • 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. Commented May 3, 2012 at 14:13
  • I am loading it in the code-behind with PHP. Commented May 3, 2012 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. Commented May 3, 2012 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. Commented May 3, 2012 at 14:38
  • If you have a problem with data picker not working after a first call, check out this answer: stackoverflow.com/a/16283547/1329910 Your problem may have to do with datepicker adding its own class: hasDatepicker Commented Apr 29, 2013 at 16:43

13 Answers 13

303

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"

Sign up to request clarification or add additional context in comments.

18 Comments

This is a solution that would work in any kind of dynamic appending. +1 to you.
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.
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
You might want to add a filter :not(.hasDatepicker)
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');
|
51

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

1 Comment

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.
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();
    }

});

1 Comment

Could that then be shortened to $('body').on('focus',".datepicker:not(.hasDatepicker)", function(){$(this).datepicker();});?
14

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();

1 Comment

Exactly right! Dynamically loaded elements ended up not being the issue for me, so this solution worked.
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();
});

1 Comment

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.
2

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

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

Comments

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
});

Comments

1
 $('body').on('focus',".my_date_picker", function(){
            $(this).datepicker({
                minDate: new Date(),
            });
        });

Comments

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.

Comments

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', });

Comments

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

Comments

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/

Comments

0
$( ".datepicker_recurring_start" ).each(function(){
    $(this).datepicker({
        dateFormat:"dd/mm/yy",
        yearRange: '2000:2012',
        changeYear: true,
        changeMonth: true
    });
});

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.