jQuery comment lier un événement onclick à un élément HTML ajouté dynamiquement
je veux lier un événement onclick à un élément que j'insère dynamiquement avec jQuery
mais il n'exécute jamais la fonction liée. Je serais heureux si vous pouvez rappeler pourquoi cet exemple ne fonctionne pas et comment je peux l'obtenir pour fonctionner correctement:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="da" lang="da">
<head>
<title>test of click binding</title>
<script src="https://code.jquery.com/jquery-1.12.4.min.js"></script>
<script type="text/javascript">
jQuery(function(){
close_link = $('<a class="" href="#">Click here to see an alert</a>');
close_link.bind("click", function(){
alert('hello from binded function call');
//do stuff here...
});
$('.add_to_this').append(close_link);
});
</script>
</head>
<body>
<h1 >Test of click binding</h1>
<p>problem: to bind a click event to an element I append via JQuery.</p>
<div class="add_to_this">
<p>The link is created, then added here below:</p>
</div>
<div class="add_to_this">
<p>Another is added here below:</p>
</div>
</body>
</html>
EDIT: j'ai modifié l'exemple pour contenir deux éléments auxquels la méthode est insérée. dans ce cas, l'appel alert()
n'est jamais exécuté. (merci à @Daff d'avoir souligné cela dans un commentaire)
9 réponses
Le premier problème est que lorsque vous appelez ajouter sur un jQuery définir avec plus d'un élément, un clone de l'élément à ajouter est créé pour chacun et donc de l'événement attaché observateur est perdu.
, Une autre façon de le faire serait de créer un lien pour chaque élément:
function handler() { alert('hello'); }
$('.add_to_this').append(function() {
return $('<a>Click here</a>').click(handler);
})
un autre problème potentiel pourrait être que l'observateur d'événement est attaché avant que l'élément ait été ajouté au DOM. Je ne sais pas si cela a quelque chose pour dire, mais je pense que le comportement pourrait être considéré comme indéterminé. Une approche plus solide serait probablement:
function handler() { alert('hello'); }
$('.add_to_this').each(function() {
var link = $('<a>Click here</a>');
$(this).append(link);
link.click(handler);
});
Toutes ces méthodes sont obsolètes. Vous devez utiliser la méthode on
pour résoudre votre problème.
si vous voulez cibler un élément ajouté dynamiquement, vous devrez utiliser
$(document).on('click', selector-to-your-element , function() {
//code here ....
});
remplacer la méthode dépréciée .live()
.
et la méthode Live?
$('.add_to_this a').live('click', function() {
alert('hello from binded function call');
});
toujours, ce que vous avez fait à propos de l'apparence comme il devrait fonctionner. Il y a un autre post qui ressemble assez similaire.
un peu tard pour la fête, mais j'ai pensé que je pourrais essayer de clarifier certaines idées fausses communes dans jQuery event handlers. À partir de jQuery 1.7, .on()
devrait être utilisé à la place du .live()
déprécié , pour déléguer les gestionnaires d'événements aux éléments qui sont créés dynamiquement à tout moment après que le gestionnaire d'événements est assigné.
cela dit, il n'est pas simple de changer live
pour on
parce que la syntaxe est légèrement différente:
nouvelle méthode (exemple 1):
$(document).on('click', '#someting', function(){
});
méthode dépréciée (exemple 2):
$('#something').live(function(){
});
Comme indiqué ci-dessus, il y a une différence. La torsion est .on()
peut en fait être appelé similaire à .live()
, en passant le sélecteur à la fonction jQuery elle-même:
exemple 3:
$('#something').on('click', function(){
});
cependant, sans utiliser $(document)
comme dans l'exemple 1, l'exemple 3 NE FONCTIONNERA PAS pour éléments créés dynamiquement. L'exemple 3 est absolument parfait si vous n'avez pas besoin de la délégation dynamique.
Doit $(document).() peut être utilisé pour tout?
cela fonctionnera, mais si vous n'avez pas besoin de la délégation dynamique, il serait plus approprié d'utiliser l'exemple 3 parce que l'exemple 1 nécessite un peu plus de travail à partir du navigateur. Il n'y aura pas d'impact réel sur la performance mais il est logique d'utiliser le plus méthode appropriée pour votre utilisation.
devrait .() peut être utilisé au lieu de .cliquez sur () si aucune délégation dynamique n'est nécessaire?
pas nécessairement. Ce qui suit n'est qu'un raccourci pour l'exemple 3:
$('#something').click(function(){
});
ce qui précède est parfaitement valable et c'est donc une question de préférence personnelle quant à la méthode utilisée lorsqu'aucune délégation dynamique n'est requise.
références:
considérez ceci:
jQuery(function(){
var close_link = $('<a class="" href="#">Click here to see an alert</a>');
$('.add_to_this').append(close_link);
$('.add_to_this').children().each(function()
{
$(this).click(function() {
alert('hello from binded function call');
//do stuff here...
});
});
});
cela fonctionnera parce que vous l'attachez à chaque élément spécifique. C'est pourquoi vous avez besoin - après avoir ajouté votre lien vers le DOM - de trouver un moyen de sélectionner explicitement votre élément ajouté en tant qu'élément JQuery dans le DOM et d'y lier l'événement de clic.
la meilleure façon sera probablement - comme suggéré - de le lier à une classe spécifique via la méthode live.
je crois que la bonne façon de le faire:
$('#id').append('<a id="#subid" href="#">...</a>');
$('#subid').click( close_link );
Il est possible et parfois nécessaire pour créer l'événement click avec l'élément. C'est par exemple le cas lorsque la liaison par sélecteur n'est pas une option. L'essentiel est d'éviter le problème dont parlait Tobias en utilisant .replaceWith()
sur un seul élément. Notez qu'il ne s'agit que d'une validation de principe.
<script>
// This simulates the object to handle
var staticObj = [
{ ID: '1', Name: 'Foo' },
{ ID: '2', Name: 'Foo' },
{ ID: '3', Name: 'Foo' }
];
staticObj[1].children = [
{ ID: 'a', Name: 'Bar' },
{ ID: 'b', Name: 'Bar' },
{ ID: 'c', Name: 'Bar' }
];
staticObj[1].children[1].children = [
{ ID: 'x', Name: 'Baz' },
{ ID: 'y', Name: 'Baz' }
];
// This is the object-to-html-element function handler with recursion
var handleItem = function( item ) {
var ul, li = $("<li>" + item.ID + " " + item.Name + "</li>");
if(typeof item.children !== 'undefined') {
ul = $("<ul />");
for (var i = 0; i < item.children.length; i++) {
ul.append(handleItem(item.children[i]));
}
li.append(ul);
}
// This click handler actually does work
li.click(function(e) {
alert(item.Name);
e.stopPropagation();
});
return li;
};
// Wait for the dom instead of an ajax call or whatever
$(function() {
var ul = $("<ul />");
for (var i = 0; i < staticObj.length; i++) {
ul.append(handleItem(staticObj[i]));
}
// Here; this works.
$('#something').replaceWith(ul);
});
</script>
<div id="something">Magical ponies ♥</div>
function load_tpl(selected=""){
$("#load_tpl").empty();
for(x in ds_tpl){
$("#load_tpl").append('<li><a id="'+ds_tpl[x]+'" href="#" >'+ds_tpl[x]+'</a></li>');
}
$.each($("#load_tpl a"),function(){
$(this).on("click",function(e){
alert(e.target.id);
});
});
}
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script>
$(document).ready(function(){
$(document).on('click', '.close', function(){
var rowid='row'+this.id;
var sl = '#tblData tr[id='+rowid+']';
console.log(sl);
$(sl).remove();
});
$("#addrow").click(function(){
var row='';
for(var i=0;i<10;i++){
row=i;
row='<tr id=row'+i+'>'
+ '<td>'+i+'</td>'
+ '<td>ID'+i+'</td>'
+ '<td>NAME'+i+'</td>'
+ '<td><input class=close type=button id='+i+' value=X></td>'
+'</tr>';
console.log(row);
$('#tblData tr:last').after(row);
}
});
});
</script>
</head>
<body>
<br/><input type="button" id="addrow" value="Create Table"/>
<table id="tblData" border="1" width="40%">
<thead>
<tr>
<th>Sr</th>
<th>ID</th>
<th>Name</th>
<th>Delete</th>
</tr>
</thead>
</table>
</body>
</html>