2010-03-14 53 views
14

Tengo un div en el que hay un datepicker. Utilizo algo como esto para clonarlo:problema al clonar jQuery UI datepicker

mydiv = $('#someDiv'); 

// works fine so far 
mydiv.find('input.datefield').datepicker(); 

// clone without the events and insert 
newDiv = myDiv.clone(false).insertAfter(myDiv); 

// datepicker won't re-init if this class is present 
newDiv.find('.hadDatepicker').removeClass('hadDatepicker'); 

// reinitialize datepicker 
newDiv.find('input.datefield').datepicker(); 

Esta es una versión simplificada de mi código. Funciona y el calendario aparece como se espera donde se espera ... pero cuando se hace clic en una fecha, el anterior el valor del datepicker se actualiza ... (aquel desde el que se clonó).

He tratado de destruir la instancia (inexisting) antes de la siguiente manera:

newDiv.find('input.datefield').datepicker('destroy').datepicker(); 

No hubo suerte ..

He comprobado cómo se realiza un seguimiento de los casos y de forma manual borran los datos como esto:

newDiv.find('input.datefield').data('datepicker', false).datepicker('destroy').datepicker(); 

Todavía no hubo suerte.

Lo que no entiendo es que solo el comportamiento de selección de fechas tiene errores, todo lo demás funciona como se esperaba.

Realmente no sé qué más para comprobar ahora ..

Respuesta

23

Aquí está el problema. datepicker crea atributos de ID basados ​​en UUID para los campos de entrada a los que se une cuando lo inicializa. Al clonar esos elementos se obtienen más elementos con el mismo ID (que a jQuery no le gusta) o un ID diferente si su rutina de clonación lo gestiona (lo que significa que datepicker no conoce los clones). En otras palabras, datepicker solo inicializa todos los elementos que coinciden con su selector en el momento en que lo llama. en realidad tiene menos sentido intentar destruir/deshabilitar/habilitar una y otra vez, cuando simplemente puede ajustar la llamada de inicio dentro de cualquier función que use para crear los clones.

Debido a que mis funciones de clonación normalmente copian elementos de DOM ocultos en lugar de los visibles, tengo el lujo de decidir si necesito vincular antes o después de la clonación. Por lo tanto, haga de #templateDiv un elemento oculto en su página con el elemento INPUT que ya está allí.

mydiv = $('#templateDiv'); 
mydest = $('#someDiv'); 

function make_the_donuts() { 
    newDiv = myDiv.clone(true).insertAfter(mydest); 
    // attach datepickers by instance rather than by class 
    newDiv.find('input.datefield').datepicker(); 
} 

y eso más o menos lo hace. Clona (verdadero) siempre que puedas, te ahorrará dolores de cabeza a largo plazo.

+0

Gracias, creo que realmente señalaron mi problema. –

0

¿Qué hay de cambiar el orden?

mydiv = $('#someDiv'); 

// clone without the events and insert 
newDiv = myDiv.clone(false).insertAfter(myDiv); 

// datepicker won't re-init if this class is present 
// not necessary anymore 
// newDiv.find('.hadDatepicker').removeClass('hadDatepicker'); 

newDiv.find('input.datefield').datepicker(); 

// datepicker attached as a last step 
mydiv.find('input.datefield').datepicker(); 

Honestamente, no sé cómo funciona datepicker internamente. Mi presentimiento es que almacena algo en el almacenamiento de jQuery DOM. Evitemos copiarlo a toda costa.

(Es posible que tenga lógica de negocio de largo entre estas líneas de código. El punto es tener una copia de seguridad antes de poner #someDiv un selector de fechas en ella.)

+0

este es mi problema .. digamos que tengo 2 mesas filas con formas dinámicas complejas en ellos. Hay un botón "+" que al hacer clic en copiar el DOM de la última fila e insertarlo de nuevo después de esa última fila. Así que el primer selector de fechas * * ha de ser activado primero y el segundo podría o no podría obtener permitido .. –

+0

http://vonautomatisch.at/media/uploads/grappelli/inlinetabular_big.jpg como no .. pero con datepickers. –

+0

@ h3: Todavía no entiendo por qué no se puede hacer una copia de un disco limpio. La copia de seguridad no tiene que ser insertada en el DOM ... – pestaa

0

Asegúrese de que el selector de fechas recién clonado tiene un nombre diferente y ID que el original. Si ambos tienen el mismo nombre, entonces el comportamiento que describes sería normal.

trate de cambiar la última línea a algo como:

newDiv.find('input.datefield').attr('id', 'newDatePicker').attr('name', 'newDatePicker').datepicker(); 
+0

Es más probable que tenga clases asociadas, simplemente nos proporcionó una identificación por motivos de presentación. – pestaa

36

Esto funciona para mí con jQuery UI 1.7.2

var mydiv = $('#someDiv'); 
mydiv.find('input.datefield').datepicker(); 
var newDiv = mydiv.clone(false).attr("id", "someDiv2").insertAfter(mydiv); 
newDiv.find('input.datefield') 
    .attr("id", "") 
    .removeClass('hasDatepicker') 
    .removeData('datepicker') 
    .unbind() 
    .datepicker(); 

Comprobar http://jsbin.com/ahoqa3/2 para una demostración rápida

por cierto. parece que tienes diferentes errores en el código de tu pregunta. La clase CSS es hasDatepicker no hadDatepicker y al mismo tiempo escribió mydiv y la próxima vez la variable es myDiv que no es lo mismo.

+1

Excelente. Sé que esto es viejo, pero esta respuesta resolvió el problema cuando lo encontré esta mañana, lo he convertido en una pequeña función que puedo reutilizar donde sea necesario: 'function initialiseDates() { $ ('. DatePicker ') .each (function() { $ (this) .removeClass (' hasDatepicker '). removeData (' datepicker '). unbind(). datepicker ({dateFormat:' dd/mm/aa '});; }); }; ' Perfecto, gracias! : D –

+0

Buen trabajo.Pero si clona toda la fila de un formulario (por ejemplo, datos de personas invitadas), row puede contener otros campos de entrada, que pueden tener diferentes validadores de datos de entrada, que no queremos perder. En este caso, debe destruir datepicker en myDiv y hacer clone (verdadero), luego init datepicker nuevamente para myDiv. Antes de datepicker de inicialización en newDiv, borre su id .attr ("id", ""). Me ayudó. –

+0

Siguiendo con el comentario de @JamieHartnoll: si tiene 2 campos, está clonando y usando clases, la salsa secreta para mí fue recorrer el nuevo clon de su porción de código; luego revise cada uno y '$ (this) .removeData ('datepicker'). unbind(). datepicker ({format: 'yourformathere'});' – pjammer

3

Eso sí,

$('input.datefield').datepicker("destroy"); 

antes de la clonación de la div. A continuación, después de insertar el clon se unen al nuevo selector de fechas

$('input.datefield').datepicker(); 

tipo de solución 'hacky' pero funciona perfectamente.

1
$('input.datefield').datepicker("destroy"); 
$('input.datefield').datepicker(); 

funciona bien. Pero simplemente haciendo esto, datepicker se abrirá en la entrada clonada y establecerá la fecha en la entrada original (porque tienen la misma ID)

para resolver esto debe cambiar el atributo id de la entrada clonada.

dp = < cloned input > 
var d = $('input.vDateField'); 
dp.removeClass('hasDatepicker'); 
dp.attr('id', dp.attr('id')+d.length); 
d.datepicker("destroy"); 
d.datepicker(); 

y funcionará genial!

+0

¡Me pareció muy útil gracias! – user1190132

7

Si llama al .datepicker('destroy').removeAttr('id') antes de clonar y luego vuelve a iniciar el selector de fecha, funcionará.

Esto parece ser un error con la destrucción ya que se supone que devuelve el elemento a su estado original.

+0

esto me ha estado molestando por días. Podría agregar datapickers, pero no estaba funcionando después de la segunda fila, porque 'id' era siempre el mismo. al agregar removeAttr ('id') lo arregló. eso! @dfmiller – Aris

+0

Esto funcionó para mí –

0

La solución completa que funciona para mí.

//before 
$('input.fecha').datepicker("destroy"); 
newcell.innerHTML = table.rows[0].cells[i].innerHTML; 
//change de input id 
$("input.fecha").attr("id", function (arr) {return "fecha" + arr;}); 
//after 
$('input.fecha').datepicker({defaultDate: "+1w",changeMonth: true,numberOfMonths: 1, showOn: "button", buttonImage: "<?php echo base_url() ?>images/calendar.gif", buttonImageOnly: true, showLabel:false, dateFormat:"yy-mm-dd"}); 

Y la tabla html td.

<td><?php echo form_input(array('name' => 'fecha','id' => 'fecha','class' => 'fecha')); ?></td> 

Espero que te ayude.

Buenos días

0
var dt = new Date(); 
var month = dt.getMonth(); 
var day = dt.getDate(); 
var year = dt.getFullYear()-5; 
      $newClone.children().children("#fna"+clickID) 
    .attr({ 
     'id': 'fna1'+newID, 
     'name': 'fna'+newID, 
     'value': day + '-' + month + '-' + year 
    }) 
    .datepicker("destroy") 
    .datepicker({ 
     firstDay: 1, 
     changeMonth: true, 
     changeYear: true, 
     yearRange: 'c-100:c', 
     defaultDate: '-1y', 
     dateFormat: 'dd-mm-yy' , 
     nextText: "Mes siguiente", 
     prevText: "Mes anterior", 
     monthNamesShort: ['Ene','Feb','Mar','Abr','May','Jun','Jul','Ago','Sep','Oct','Nov','Dic'], 
     dayNamesMin: ['Do', 'Lu', 'Ma', 'Mi', 'Ju', 'Vi', 'Sa'] 
    }); 
+1

por favor use solo INGLÉS como su idioma, no otro. –

+0

Quiero decir, no hay una regla sobre qué idioma se puede hablar ... Sí, la programación solo es INGLÉS PERO el nombre de las variables puede estar en cualquier idioma ... ¡al final solo es una cadena! –

0

Esto podría ser un poco tarde, pero todas las sugerencias anteriores no funcionaron para mí, se me ocurrió una solución fácil para esto.

Primero, cuál es la causa del problema: JQuery asigna datepicker al elemento id. si está clonando un elemento, también se puede clonar el mismo id. que a jQuery no le gusta Puede terminar recibiendo el error de referencia nulo o la fecha asignada al primer campo de entrada, sin importar en qué campo de entrada haga clic.

Solución:

1) destruir selector de fechas 2) asignar nuevos identificadores únicos a todos los campos de entrada 3) asignar selector de fechas para cada entrada

Asegúrese de que su entrada es algo como esto

<input type="text" name="ndate[]" id="date1" class="n1datepicker"> 

Antes de clonar, destruir datepicker

$('.n1datepicker').datepicker('destroy'); 

Después de clonar, añadir estas líneas, así

var i = 0; 
$('.n1datepicker').each(function() { 
    $(this).attr("id",'date' + i).datepicker(); 
    i++; 
}); 

y la magia sucede

0

selector de fechas no si se cambia el ID de un elemento. Por lo tanto, es mejor no cambiar la identificación de un elemento si es necesario. Pero si usted realmente necesita para cambiar el ID y que el ID cambiado necesita trabajar con selector de fechas luego seguir:

$(selector).removeClass('hasDatepicker'); 
 
$(selector).datepicker({ 
 
    changeMonth: true, 
 
    changeYear: true 
 
});