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!

durchtränkt
quelle
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".

ilyes kooli
quelle
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

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

});
pleshy
quelle
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();
wintondeshong
quelle
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();
});
Tr1stan
quelle
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
});
Hady Shaltout
quelle
1

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

$('body').on('focus', '.datepicker', function() {
 $(this).removeClass('hasDatepicker').datepicker();
});
Vinicius Avelino Alcantara
quelle
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.

Chris
quelle
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', });
Nada N. Hantouli
quelle
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

c0x6a
quelle
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/

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