jQuery clone () ne clonant pas les liaisons d'événements, même avec on ()

100

J'ai créé une série d'événements jQuery personnalisés à utiliser dans les applications Web mobiles. Ils fonctionnent très bien et ont été testés. Cependant, j'ai rencontré un petit problème que j'ai du mal à comprendre.

J'utilise .clone()sur quelques éléments du DOM, qui contiennent un bouton. Le bouton a certains des événements personnalisés liés (les événements sont liés à l'aide de .on()), mais. Malheureusement, lorsque j'utilise jQuery .clone(), les liaisons ne sont pas conservées et je dois les ajouter à nouveau.

Quelqu'un a-t-il déjà rencontré ce problème, est-ce que quelqu'un connaît une solution potentielle? Je pensais que l'utilisation .on()était censée préserver la liaison des éléments qui existent maintenant ou dans le futur?

BenM
la source
"Je pensais qu'utiliser .on () était censé préserver la liaison des éléments qui existent maintenant ou dans le futur?" - Cela n'a pas grand-chose à voir avec .clone; c'est la logique de délégation d'événements de jQuery et fonctionne si vous passez un sélecteur supplémentaire à .on.
pimvdb

Réponses:

213

Je pense que vous devriez utiliser cette surcharge de la méthode .clone () :

$element.clone(true, true);

clone ([withDataAndEvents] [, deepWithDataAndEvents])

withDataAndEvents : un booléen indiquant si les gestionnaires d'événements et les données doivent être copiés avec les éléments. La valeur par défaut est false.

deepWithDataAndEvents : valeur booléenne indiquant si les gestionnaires d'événements et les données de tous les enfants de l'élément cloné doivent être copiés. Par défaut, sa valeur correspond à la valeur du premier argument (qui vaut par défaut false).


Attention, cela .on()ne lie pas réellement les événements aux cibles mais à l'élément auquel vous déléguez. Donc si vous avez:

$('#container').on('click', '.button', ...);

Les événements sont en fait liés #container. Lorsqu'un clic sur un .buttonélément se produit, il apparaît jusqu'à l' #containerélément. L'élément qui a déclenché l'événement est évalué sur le paramètre de sélection de .on()et s'il correspond, le gestionnaire d'événements est exécuté. C'est ainsi que fonctionne la délégation d'événements.

Si vous clonez l'élément #container, vous devez effectuer un clonage en profondeur avec des événements et des données pour que les liaisons établies avec .on()soient préservées.

Cela ne serait pas nécessaire si vous utilisiez .on()sur un parent de #container.

Didier Ghys
la source
20
Je n'ai jamais connu .clone()les arguments acceptés. FML. Merci de votre aide.
BenM
1
@DidierGhys Merci, j'ai eu du mal à .clone()ne pas cloner le .data()(à la fois data-xxxx="somedata"et les données dans le DOM) .. Cela corrige le problème aussi!
Richard de Wit
J'ai posé cette question , mais personne ne m'a répondu. Pouvez-vous m'aider?
Ali Soltani
Excellent, j'ai dû faire un clickévénement pour ajouter la nouvelle div clonée. readyne fonctionnait pas
csandreas1
4

Vous devez être conscient du fait que la fonctionnalité de clonage profond a été ajoutée à la version 1.5 de jQuery.

Plus d'infos sur ce sujet:

http://api.jquery.com/clone/

Giedrius Vičkus
la source