poner datepicker () en elementos creados dinámicamente - JQuery / JQueryUI


115

He creado cuadros de texto dinámicamente y quiero que cada uno de ellos pueda mostrar un calendario al hacer clic. El código que estoy usando es:

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

Lo cual solo funcionará en el primer cuadro de texto, aunque todos mis cuadros de texto tienen una clase llamada datepicker_recurring_start.

¡Su ayuda es muy apreciada!


Cuando dice "creado dinámicamente", ¿quiere decir con código subyacente antes de que se cargue la página o con javascript después de la carga de la página? Porque si los elementos se agregan después de la carga de la página, deberá volver a enlazar el calendario cada vez que se agregue un nuevo cuadro de texto.
DangerMonkey

Lo estoy cargando en el código subyacente con PHP.
empapado

Creo que puede que se esté confundiendo, pero luego es difícil saberlo con la información que ha proporcionado. Entonces, solo para confirmar, ¿puede confirmar lo que quiere decir con 'cuadros de texto creados dinámicamente' por favor?
Tr1stan

Si estoy cargando 'página uno', php mira la base de datos para ver cuántos cuadros de texto de fecha hay en 'página uno' y lo muestra. Entonces, cuando se cargue la 'página uno', habrá 4 cuadros de texto que deben cargar el selector de fechas (). 'page two' tiene 7 cuadros de texto que necesitan cargar la función datepicker ().
empapado

Si tiene un problema con el selector de datos que no funciona después de una primera llamada, consulte esta respuesta: stackoverflow.com/a/16283547/1329910 Su problema puede tener que ver con datepicker agregando su propia clase: hasDatepicker
Vlad

Respuestas:


270

aquí está el truco:

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

MANIFESTACIÓN

La $('...selector..').on('..event..', '...another-selector...', ...callback...);sintaxis significa:
agregue un oyente a ...selector..( bodyen nuestro ejemplo) para el evento ..event..('foco' en nuestro ejemplo). Para todos los descendientes de los nodos coincidentes que coincidan con el selector ...another-selector...( .datepicker_recurring_starten nuestro ejemplo), aplique el controlador de eventos ...callback...(la función en línea en nuestro ejemplo)

Ver http://api.jquery.com/on/ y especialmente la sección sobre "eventos delegados"


4
Esta es una solución que funcionaría en cualquier tipo de adición dinámica. +1 para ti.
DangerMonkey

5
Aunque me parece extraño que quieras llamar .datapicker()cada vez que el cuadro de texto se enfoque, por lo que deberías tener cuidado con este enfoque (asumiendo que estoy leyendo esto bien). Sin embargo, creo que estaría bien con el .datapicker()porque probablemente verificará si se crea un selector de fecha antes de intentar recrearlo. Con otro código, es posible que no tenga esta gracia. Además, .on (solo se presenta en JQuery 1.7, así que asegúrese de usar la versión correcta.
Tr1stan

3
datepicker es lo suficientemente inteligente como para verificar si ya está creado o no (todos los componentes de jQueryUI por cierto) si la versión de jQuery está por debajo de 1.7, simplemente puede usar live
ilyes kooli

7
Es posible que desee agregar un filtro:not(.hasDatepicker)
Salman A

1
Tenga cuidado con el uso de jQuery.clone () dentro de un área que incluye un selector de fechas. Si lo hace, agregue esto para eliminar la clase hasDatepicker Y el id datepicker agrega a su entrada: .... find ('input.hasDatepicker'). RemoveClass ('hasDatepicker'). RemoveAttr ('id');
yahermann

44

Para mí, a continuación, jquery funcionó:

cambiando "cuerpo" a documento

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

Gracias a skafandri

Nota: asegúrese de que su identificación sea diferente para cada campo


Correcto - para mí tengo que usar $ (documento) y no $ ('cuerpo') - Una especie de problema con pequeños fragmentos de código. Puedo hacer que el ejemplo funcione sin problemas, pero tan pronto como agrego un montón de mi javascript en un violín, este código ya no me funciona. Aunque gracias a ambos.
Tom Stickel

16

Excelente respuesta de skafandri +1

Esto se acaba de actualizar para comprobar la clase hasDatepicker.

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

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

});

1
¿Podría entonces reducirse a $('body').on('focus',".datepicker:not(.hasDatepicker)", function(){$(this).datepicker();});?
Luke Stevenson

11

Asegúrese de que su elemento con la .date-pickerclase NO tenga ya una hasDatepickerclase. Si lo hace, incluso un intento de reinicialización con $myDatepicker.datepicker();fallará. En su lugar, debes hacer ...

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

¡Exactamente correcto! Los elementos cargados dinámicamente terminaron no siendo el problema para mí, por lo que esta solución funcionó.
Sterling Beason

6

Debe ejecutar .datepicker();nuevamente después de haber creado dinámicamente los otros elementos del cuadro de texto.

Recomendaría hacerlo en el método de devolución de llamada de la llamada que agrega los elementos al DOM.

Entonces, digamos que está utilizando el método JQuery Load para extraer los elementos de una fuente y cargarlos en el DOM, haría algo como esto:

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

1
Esto no siempre funciona en la práctica según mi experiencia. El mejor de los casos es agregar ID únicos a sus elementos y usar esos ID para hacer referencia a ellos y aplicar el selector de fecha. Parece que internamente el complemento usa esos selectores.
Wes Johnson

1

El nuevo método para los elementos dinámicos es MutationsObserver . El siguiente ejemplo usa underscore.js para usar la función (_.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

Esto fue lo que funcionó para mí (usando jquery datepicker):

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

0

Ninguna de las otras soluciones funcionó para mí. En mi aplicación, agrego los elementos del rango de fechas al documento usando jquery y luego les aplico datepicker. Entonces, ninguna de las soluciones de eventos funcionó por alguna razón.

Esto es lo que finalmente funcionó:

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

Espero que esto ayude a alguien porque esto me hizo retroceder un poco.


0

puede agregar la clase .datepicker en una función de javascript, para poder cambiar dinámicamente el tipo de entrada

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

0

He modificado la respuesta de @skafandri para evitar volver a aplicar el datepickerconstructor a todas las entradas con la .datepicker_recurring_startclase.

Aquí está el HTML:

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

Aquí está el JS:

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

aquí hay una demostración funcional


0

Esto es lo que funcionó para mí en JQuery 1.3 y se muestra en el primer clic / enfoque

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

esto necesita que tu entrada tenga la clase 'mostrar_calendario'

Live es para JQuery 1.3+ para las versiones más nuevas necesita adaptar esto a "on"

Vea más sobre la diferencia aquí http://api.jquery.com/live/


0
$( ".datepicker_recurring_start" ).each(function(){
    $(this).datepicker({
        dateFormat:"dd/mm/yy",
        yearRange: '2000:2012',
        changeYear: true,
        changeMonth: true
    });
});
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.