2010-03-14 6 views
14

J'ai un div dans lequel il y a un piqueur de date. J'utilise quelque chose comme ça pour le cloner:problème lors du clonage 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(); 

Ceci est une version allégée de mon code. Cela fonctionne et le calendrier apparaît comme prévu où il est prévu .. mais quand une date est cliquée, la valeur précédente de datepicker est mise à jour .. (celle à partir de laquelle elle a été clonée) précédente.

J'ai essayé de détruire le (inexisting) par exemple avant comme celui-ci:

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

Pas de chance ..

J'ai vérifié la façon dont il garde la trace des instances et effacé manuellement les données comme ceci:

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

Toujours pas de chance. Ce que je ne comprends pas, c'est que seul le comportement de sélection de date est bogué, tout le reste fonctionne comme prévu.

Je ne sais vraiment pas quoi d'autre pour vérifier maintenant ..

Répondre

23

Voici le problème. datepicker crée des attributs d'ID basés sur UUID pour les champs d'entrée qu'il lie lorsque vous l'initialisez. Si vous clonez ces éléments, vous obtenez plus d'éléments avec le même ID (que jQuery n'aime pas) ou un ID différent si votre routine clone gère cela (ce qui signifie que datepicker ne connaît pas les clones). En d'autres termes, datepicker initialise uniquement tous les éléments correspondant à votre sélecteur au moment où vous l'appelez. il est effectivement moins logique d'essayer de détruire/désactiver/activer encore et encore, lorsque vous pouvez simplement envelopper l'appel init à l'intérieur de la fonction que vous utilisez pour créer les clones.Comme mes fonctions clones copient généralement des éléments DOM cachés plutôt que des éléments visibles, j'ai le luxe de décider si j'ai besoin de lier avant ou après le clonage. Donc, faites de #templateDiv un élément caché sur votre page avec l'élément INPUT déjà présent.

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

et à peu près cela. Cloner (vrai) chaque fois que vous le pouvez, cela vous sauvera des maux de tête à long terme.

+0

Merci, je pense que vous avez vraiment épinglé mon problème. –

0

Qu'en est-il changer l'ordre?

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(); 

Honnêtement, je ne sais pas comment datepicker fonctionne en interne. Mon intuition est qu'il stocke quelque chose dans le stockage DOM jQuery. Évitons de le copier à tout prix.

(Vous pourriez avoir à long logique d'affaires entre ces lignes de code. Le point est d'avoir une sauvegarde de #someDiv avant de mettre un datepicker là-dessus.)

+0

c'est mon problème .. disons que j'ai 2 tables rangées avec formes dynamiques complexes en eux. Il y a un bouton "+" qui, une fois cliqué, copie le DOM de la dernière rangée et l'insère après cette dernière rangée. Ainsi, le premier datepicker * a * à activer première et la seconde peut ou non obtenir permis .. –

+0

http://vonautomatisch.at/media/uploads/grappelli/inlinetabular_big.jpg comme ça .. mais avec datpickers. –

+0

@ h3: Je ne comprends toujours pas pourquoi vous ne pouvez pas faire une copie d'un certain nettoyage. La sauvegarde ne doit pas être insérée dans le DOM ... – pestaa

0

Assurez-vous que votre datepicker cloné a un nom différent et ID que l'original. Si les deux ont le même nom, alors le comportement que vous décrivez serait normal.

Essayez de changer cette dernière ligne à quelque chose comme:

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

Plus probablement, il a des classes associées, nous a juste fourni un ID pour le plaisir de la présentation. – pestaa

36

Cela fonctionne pour moi avec 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(); 

Vérifiez http://jsbin.com/ahoqa3/2 pour une démonstration rapide

btw. vous semblez avoir des erreurs différentes dans le code de votre question. La classe CSS est hasDatepicker pas hadDatepicker et à un moment vous avez écrit mydiv et la prochaine fois que la variable est myDiv qui n'est pas la même chose.

+1

Excellent. Je sais que c'est vieux, mais cette réponse a résolu le problème quand je suis tombé dessus ce matin, je l'ai transformé en une petite fonction que je peux réutiliser partout où j'ai besoin: 'function initialiseDates() { $ ('. DatePicker ') .each() { $ (this) .removeClass (' hasDatepicker '). removeData (' datepicker '). unbind(). datepicker ({dateFormat:' jj/mm/aa '});; }); }; ' Parfait, merci! : D –

+0

Bon travail.Mais si vous clonez toute la ligne d'un formulaire (par exemple, les données de personnes invitées), la ligne peut contenir d'autres champs d'entrée, qui peuvent avoir différents validateurs de données d'entrée, que nous ne voulons pas perdre. Dans ce cas, vous devez détruire datepicker sur myDiv et make clone (true), puis init datepicker à nouveau pour myDiv. Avant d'initialiser datepicker sur newDiv, effacez son id .attr ("id", ""). Ça m'a aidé. –

+0

Suite sur le commentaire @JamieHartnoll: Si vous avez 2 champs que vous êtes en train de cloner et d'utiliser des classes, la sauce secrète pour moi était de parcourir le nouveau clone de votre morceau de code; puis passez par chacun et '$ (this) .removeData ('datepicker'). unbind(). datepicker ({format: 'yourformathere'});' – pjammer

3

juste faire

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

avant le clonage du div. Puis après l'insertion du clone lier le datepicker à nouveau

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

type d'une solution « aki » mais il fonctionne parfaitement.

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

cela fonctionne bien. Mais juste cela, datepicker va ouvrir sur l'entrée clonée et définir la date à l'entrée d'origine (parce qu'ils ont le même ID)

pour résoudre ce problème, vous devez modifier l'attribut ID de l'entrée clonée.

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

et cela fonctionnera très bien!

+0

J'ai trouvé cela très utile merci! – user1190132

7

Si vous appelez .datepicker('destroy').removeAttr('id') avant de cloner puis de ré-initier le sélecteur de date, cela fonctionnera.

Cela semble être un bug avec détruire car il est censé ramener l'élément à son état d'origine.

+0

cela m'a embêté pendant des jours. Je pourrais ajouter des datpickers, mais je ne travaillais pas après la deuxième rangée, parce que 'id' était toujours le même. En ajoutant removeAttr ('id'), il l'a corrigé. thans! @dfmiller – Aris

+0

Cela a fonctionné pour moi –

0

La solution complète qui fonctionne pour moi.

//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"}); 

Et la table html td.

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

Espérons que cela vous aide.

Bonne journée

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

plz utiliser uniquement l'anglais comme langue, pas d'autre. –

+0

Je veux dire, il n'y a pas de règle sur quelle langue vous pouvez parler ... Oui, la programmation est uniquement en anglais mais le nom des variables peut être dans n'importe quelle langue ... à la fin, c'est seulement une chaîne! –

0

Cela pourrait être un peu en retard, mais toutes les suggestions ci-dessus ne fonctionnent pas pour moi, je suis venu avec une solution facile pour cela.

Tout d'abord, quel est le problème à l'origine de ce problème: JQuery attribue le datpicker à l'ID de l'élément. Si vous clonez un élément, alors le même identifiant peut également être cloné. ce que jQuery n'aime pas. Vous pourriez vous retrouver avec une erreur de référence nulle ou la date assignée au premier champ de saisie quel que soit le champ de saisie sur lequel vous cliquez.

Solution:

1) destroy datepicker 2) attribuer de nouveaux ids uniques à tous les champs d'entrée 3) assigner datepicker pour chaque entrée

Assurez-vous que votre entrée est quelque chose comme ça

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

Avant de cloner, détruire datepicker

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

Une fois que vous cloner, ajoutez ces lignes ainsi

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

et la magie se produit

0

Datepicker n'a pas si l'ID d'un élément est modifié. Donc, il vaut mieux ne pas changer l'identifiant d'un élément s'il est requis. Mais si vous vraiment besoin de changer l'ID et ID modifié doit travailler avec datepicker puis suivre:

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