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!

empapado
fuente
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"

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

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

});
agradable
fuente
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();
wintondeshong
fuente
¡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();
});
Tr1stan
fuente
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
});
Hady Shaltout
fuente
1

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

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

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

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

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