mettre datepicker () sur des éléments créés dynamiquement - JQuery / JQueryUI


116

J'ai créé des zones de texte dynamiquement et je souhaite que chacune d'elles puisse afficher un calendrier en un clic. Le code que j'utilise est:

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

Ce qui ne fonctionnera que sur la première zone de texte, même si toutes mes zones de texte ont une classe appelée datepicker_recurring_start.

Votre aide est très appréciée!


Quand vous dites "créé dynamiquement", voulez-vous dire avec code-behind avant le chargement de la page ou avec javascript après le chargement de la page? Parce que si les éléments sont ajoutés après le chargement de la page, vous devrez relier le calendrier chaque fois qu'une nouvelle zone de texte est ajoutée.
DangerMonkey

Je le charge dans le code-behind avec PHP.
trempé

Je pense que vous êtes peut-être confus, mais c'est difficile à dire avec les informations que vous avez fournies. Donc, juste pour confirmer, pouvez-vous confirmer ce que vous entendez par «zones de texte créées dynamiquement» s'il vous plaît.
Tr1stan

Si je charge la «première page», php regarde la base de données pour voir combien de zones de texte de date se trouvent dans la «première page» et l'affiche. Ainsi, lorsque la première page se charge, il y aura 4 zones de texte qui doivent charger le datepicker (). 'page deux' a 7 zones de texte qui doivent charger la fonction datepicker ().
trempé

Si vous avez un problème avec le sélecteur de données qui ne fonctionne pas après un premier appel, consultez cette réponse: stackoverflow.com/a/16283547/1329910 Votre problème peut avoir à voir avec datepicker ajoutant sa propre classe: hasDatepicker
Vlad

Réponses:


271

voici l'astuce:

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

DEMO

La $('...selector..').on('..event..', '...another-selector...', ...callback...);syntaxe signifie:
Ajouter un écouteur à ...selector..(le bodydans notre exemple) pour l'événement ..event..('focus' dans notre exemple). Pour tous les descendants des nœuds correspondants qui correspondent au sélecteur ...another-selector...( .datepicker_recurring_startdans notre exemple), appliquez le gestionnaire d'événements ...callback...(la fonction en ligne dans notre exemple)

Voir http://api.jquery.com/on/ et en particulier la section sur les "événements délégués"


4
C'est une solution qui fonctionnerait dans tout type d'ajout dynamique. +1 à vous.
DangerMonkey

5
Bien qu'il me semble étrange que vous souhaitiez appeler .datapicker()chaque fois que la zone de texte gagne le focus - vous voudrez donc faire attention avec cette approche (en supposant que je lis bien). Cependant, je pense que vous seriez d'accord avec le .datapicker()car il vérifiera probablement si un sélecteur de date est créé avant d'essayer de recréer. Avec un autre code, vous pourriez ne pas avoir cette grâce. De plus, .on (n'est introduit que dans JQuery 1.7 - alors assurez-vous que vous utilisez la bonne version.
Tr1stan

3
datepicker est assez intelligent pour vérifier s'il est déjà créé ou non (tous les composants jQueryUI d'ailleurs) si la version de jQuery est inférieure à 1.7, vous pouvez simplement utiliser live
ilyes kooli

7
Vous voudrez peut-être ajouter un filtre:not(.hasDatepicker)
Salman A

1
Méfiez-vous d'utiliser jQuery.clone () dans une zone qui inclut un sélecteur de date. Si vous le faites, ajoutez ceci pour supprimer la classe hasDatepicker ET l'id datepicker ajoute à votre entrée: .... find ('input.hasDatepicker'). RemoveClass ('hasDatepicker'). RemoveAttr ('id');
yahermann

45

Pour moi ci-dessous jquery a fonctionné:

changement de "corps" en document

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

Merci à skafandri

Remarque: assurez-vous que votre identifiant est différent pour chaque champ


Correct - pour moi, je dois utiliser $ (document) et non $ ('body') - Tri du problème avec de petits extraits de code. Je peux faire fonctionner l'exemple sans problème, mais et dès que j'ajoute un tas de mon javascript dans un violon, ce code ne fonctionne plus pour moi. Merci aux deux.
Tom Stickel

16

Excellente réponse de skafandri +1

Ceci est juste mis à jour pour vérifier la classe hasDatepicker.

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

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

});

1
Cela pourrait-il alors être abrégé $('body').on('focus',".datepicker:not(.hasDatepicker)", function(){$(this).datepicker();});?
Luke Stevenson

11

Assurez-vous que votre élément avec la .date-pickerclasse n'a PAS déjà de hasDatepickerclasse. Si c'est le cas, même une tentative de réinitialisation avec $myDatepicker.datepicker();échouera! Au lieu de cela, vous devez faire ...

$myDatepicker.removeClass('hasDatepicker').datepicker();

Exactement raison! Les éléments chargés dynamiquement n'ont finalement pas été le problème pour moi, donc cette solution a fonctionné.
Sterling Beason

6

Vous devez réexécuter le .datepicker();après avoir créé dynamiquement les autres éléments de zone de texte.

Je recommanderais de le faire dans la méthode de rappel de l'appel qui ajoute les éléments au DOM.

Supposons que vous utilisiez la méthode JQuery Load pour extraire les éléments d'une source et les charger dans le DOM, vous feriez quelque chose comme ceci:

$('#id_of_div_youre_dynamically_adding_to').load('ajax/get_textbox', function() {
  $(".datepicker_recurring_start" ).datepicker();
});

1
Cela ne fonctionne pas toujours dans la pratique d'après mon expérience. Le meilleur cas est d'ajouter des identifiants uniques à vos éléments et d'utiliser ces identifiants pour les référencer et appliquer le sélecteur de date. Il semble qu'en interne, le plugin utilise ces sélecteurs.
Wes Johnson

1

La nouvelle méthode pour les éléments dynamiques est MutationsObserver .. L'exemple suivant utilise le soulignement.js pour utiliser la fonction (_.each).

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

1

C'est ce qui a fonctionné pour moi (en utilisant jquery datepicker):

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

0

Aucune des autres solutions n'a fonctionné pour moi. Dans mon application, j'ajoute les éléments de la plage de dates au document à l'aide de jquery, puis je leur applique le sélecteur de date. Aucune des solutions événementielles n'a donc fonctionné pour une raison quelconque.

C'est ce qui a finalement fonctionné:

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

J'espère que cela aide quelqu'un parce que cela m'a un peu reculé.


0

vous pouvez ajouter la classe .datepicker dans une fonction javascript, pour pouvoir changer dynamiquement le type d'entrée

 $("#ddlDefault").addClass("datepicker");
 $(".datepicker").datetimepicker({ timepicker: false, format: 'd/m/Y', });

0

J'ai modifié la réponse @skafandri pour éviter de réappliquer le datepickerconstructeur à toutes les entrées avec .datepicker_recurring_startclasse.

Voici le HTML:

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

Voici le JS:

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

voici une démo fonctionnelle


0

C'est ce qui a fonctionné pour moi sur JQuery 1.3 et qui s'affiche au premier clic / focus

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

cela nécessite que votre entrée ait la classe 'mostrar_calendario'

Live est pour JQuery 1.3+ pour les versions plus récentes, vous devez l'adapter à "on"

En savoir plus sur la différence ici http://api.jquery.com/live/


0
$( ".datepicker_recurring_start" ).each(function(){
    $(this).datepicker({
        dateFormat:"dd/mm/yy",
        yearRange: '2000:2012',
        changeYear: true,
        changeMonth: true
    });
});
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.