Setzen von datepicker () auf dynamisch erstellte Elemente - JQuery / JQueryUI


115

Ich habe dynamisch Textfelder erstellt und möchte, dass jedes von ihnen beim Klicken einen Kalender anzeigen kann. Der Code, den ich benutze, ist:

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

Dies funktioniert nur für das erste Textfeld, obwohl alle meine Textfelder eine Klasse namens datepicker_recurring_start haben.

Deine Hilfe ist sehr Willkommen!


Wenn Sie "dynamisch erstellt" sagen, meinen Sie mit CodeBehind vor dem Laden der Seite oder mit Javascript nach dem Laden der Seite? Wenn die Elemente nach dem Laden der Seite hinzugefügt werden, müssen Sie den Kalender jedes Mal neu binden, wenn ein neues Textfeld hinzugefügt wird.
DangerMonkey

Ich lade es in den Code-Behind mit PHP.
durchtränkt

Ich denke, Sie könnten verwirrt sein, aber dann ist es schwer zu sagen, mit den Informationen, die Sie geliefert haben. Können Sie zur Bestätigung bestätigen, was Sie unter "dynamisch erstellten Textfeldern" verstehen?
Tr1stan

Wenn ich 'Seite eins' lade, sieht PHP in der Datenbank nach, wie viele Datumstextfelder in 'Seite eins' sind, und zeigt sie an. Wenn also 'Seite eins' geladen wird, gibt es 4 Textfelder, in die der Datepicker () geladen werden muss. 'Seite zwei' enthält 7 Textfelder, in die die Funktion datepicker () geladen werden muss.
durchtränkt

Wenn Sie ein Problem mit der Datenauswahl haben, die nach einem ersten Anruf nicht funktioniert, lesen Sie diese Antwort: stackoverflow.com/a/16283547/1329910 Ihr Problem hat möglicherweise damit zu tun, dass der Datepicker eine eigene Klasse hinzufügt: hasDatepicker
Vlad

Antworten:


267

Hier ist der Trick:

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

DEMO

Die $('...selector..').on('..event..', '...another-selector...', ...callback...);Syntax bedeutet:
Fügen Sie einen Listener ...selector..( bodyin unserem Beispiel) für das Ereignis hinzu ..event..(in unserem Beispiel 'focus'). Wenden Sie für alle Nachkommen der übereinstimmenden Knoten, die mit dem Selektor übereinstimmen ...another-selector...( .datepicker_recurring_startin unserem Beispiel), den Ereignishandler an ...callback...(die Inline-Funktion in unserem Beispiel).

Siehe http://api.jquery.com/on/ und insbesondere den Abschnitt über "delegierte Ereignisse".


4
Dies ist eine Lösung, die bei jeder Art von dynamischem Anhängen funktioniert. +1 für dich.
DangerMonkey

5
Obwohl es mir seltsam erscheint, dass Sie .datapicker()jedes Mal anrufen möchten, wenn das Textfeld den Fokus erhält, sollten Sie bei diesem Ansatz vorsichtig sein (vorausgesetzt, ich lese das richtig). Ich denke jedoch, dass Sie damit .datapicker()einverstanden sind, da wahrscheinlich geprüft wird, ob ein Datepicker erstellt wurde, bevor versucht wird, ihn neu zu erstellen. Mit anderem Code haben Sie diese Gnade möglicherweise nicht. Auch .on (wird nur in JQuery 1.7 eingeführt - stellen Sie also sicher, dass Sie die richtige Version verwenden.
Tr1stan

3
datepicker ist clever genug, um zu überprüfen, ob es bereits erstellt wurde oder nicht (übrigens alle jQueryUI-Komponenten). Wenn die jQuery-Version unter 1,7 liegt, können Sie einfach live
ilyes kooli

7
Vielleicht möchten Sie einen Filter hinzufügen:not(.hasDatepicker)
Salman A

1
Achten Sie darauf, jQuery.clone () nicht in einem Bereich zu verwenden, der einen Datepicker enthält. Wenn Sie dies tun, fügen Sie dies hinzu, um die hasDatepicker-Klasse zu entfernen UND die ID datepicker zu Ihrer Eingabe hinzuzufügen: .... find ('input.hasDatepicker'). RemoveClass ('hasDatepicker'). RemoveAttr ('id');
Yahermann

44

Für mich unten hat jquery funktioniert:

"Körper" in Dokument ändern

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

Danke an Skafandri

Hinweis: Stellen Sie sicher, dass Ihre ID für jedes Feld unterschiedlich ist


Richtig - für mich muss ich $ (Dokument) und nicht $ ('Körper') verwenden - Art des Problems mit kleinen Codeausschnitten. Ich kann das Beispiel problemlos zum Laufen bringen, aber sobald ich ein paar meiner Javascript in eine Geige eingefügt habe, funktioniert dieser Code für mich nicht mehr. Vielen Dank an beide.
Tom Stickel

16

Hervorragende Antwort von skafandri +1

Dies wird nur aktualisiert, um nach der hasDatepicker-Klasse zu suchen.

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

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

});

1
Könnte das dann verkürzt werden $('body').on('focus',".datepicker:not(.hasDatepicker)", function(){$(this).datepicker();});?
Luke Stevenson

11

Stellen Sie sicher, dass Ihr Element mit der .date-pickerKlasse KEINE hasDatepickerKlasse hat. Wenn dies der Fall ist, schlägt sogar ein Versuch $myDatepicker.datepicker();fehl, mit neu zu initialisieren ! Stattdessen müssen Sie tun ...

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

Genau richtig! Dynamisch geladene Elemente waren für mich kein Problem, daher funktionierte diese Lösung.
Sterling Beason

6

Sie müssen das .datepicker();erneut ausführen , nachdem Sie die anderen Textfeldelemente dynamisch erstellt haben.

Ich würde dies in der Rückrufmethode des Aufrufs empfehlen, der die Elemente zum DOM hinzufügt.

Angenommen, Sie verwenden die JQuery Load-Methode, um die Elemente aus einer Quelle abzurufen und in das DOM zu laden. Gehen Sie dazu wie folgt vor:

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

1
Dies funktioniert aus meiner Erfahrung in der Praxis nicht immer. Am besten fügen Sie Ihren Elementen eindeutige IDs hinzu und verwenden diese IDs, um sie zu referenzieren und den Datepicker anzuwenden. Es scheint, dass das Plugin intern diese Selektoren verwendet.
Wes Johnson

1

Die neue Methode für dynamische Elemente ist MutationsObserver . Im folgenden Beispiel wird die Funktion (_.each) mit underscore.js verwendet.

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

Dies war, was für mich funktioniert hat (mit jquery datepicker):

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

0

Keine der anderen Lösungen hat bei mir funktioniert. In meiner App füge ich die Datumsbereichselemente mithilfe von jquery zum Dokument hinzu und wende dann Datepicker auf sie an. Daher funktionierte keine der Event-Lösungen aus irgendeinem Grund.

Das hat endlich geklappt:

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

Hoffe das hilft jemandem, denn das hat mich ein bisschen zurückgeworfen.


0

Sie können die Klasse .datepicker in einer Javascript-Funktion hinzufügen, um den Eingabetyp dynamisch ändern zu können

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

0

Ich habe die @ skafandri-Antwort geändert, um zu vermeiden, dass der datepickerKonstruktor erneut auf alle Eingaben mit .datepicker_recurring_startKlasse angewendet wird .

Hier ist der HTML:

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

Hier ist der JS:

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

hier ist eine Arbeits Demo


0

Dies hat bei JQuery 1.3 für mich funktioniert und wird beim ersten Klicken / Fokussieren angezeigt

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

Dies setzt voraus, dass Ihre Eingabe die Klasse 'mostrar_calendario' hat.

Live ist für JQuery 1.3+ für neuere Versionen, die Sie an "on" anpassen müssen.

Weitere Informationen zum Unterschied finden Sie hier http://api.jquery.com/live/


0
$( ".datepicker_recurring_start" ).each(function(){
    $(this).datepicker({
        dateFormat:"dd/mm/yy",
        yearRange: '2000:2012',
        changeYear: true,
        changeMonth: true
    });
});
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.