Jquery new element event binding solution

  • 2020-03-30 03:18:00
  • OfStack

Js event monitoring is not the same as CSS, CSS as long as you set the style, whether the original or the new addition, have the same performance. Event listening is not. You have to bind events to each element individually.

A common example is when working with tables. There's a delete button at the end of each line, and clicking on this will delete that line.

 
<table> 
<tbody> 
<tr> 
<td> We already had it in this row </td> 
<td><buttonclass="del"> delete </button></td> 
</tr> 
<tr> 
<td> We already had it in this row </td> 
<td><buttonclass="del"> delete </button></td> 
</tr> 
</tbody> 
</table> 

Normally, I bind like this
 
jQuery(function($){ 
//A delete button already initializes the binding delete event
$(".del").click(function() { 
$(this).parents("tr").remove(); 
}); 
}); 

For the delete button that existed before domready, everything is perfect. But if you add a few lines dynamically with js after domready, those buttons in the new lines will lose any effect.

How to solve this problem? Here are four solutions:

Solution 0 - onclick

In general, I do this if I ignore the principle of separation of structure and behavior.
Note that the deltr function must be a global function and must be placed outside jQuery(function($) {}). If you put it inside, it will become a local function.

<td><buttononclick="deltr(this)"> delete </button></td> 

jQuery(function($){ 
//Add the line
$("#add2").click(function(){ 
$("#table2>tbody").append('<tr><td> The new line </td><td><button nclick="deltr(this)"> delete </button></td></tr>') 
}); 
}); 
//Delete row function, must be placed outside the domready function
function deltr(delbtn){ 
$(delbtn).parents("tr").remove(); 
}; 

Solution # 1 - repeat binding

That is, when domready binds an event handler to an existing element,
It is then bound again when a new element is added.

<td><buttonclass="del"> delete </button></td> 

jQuery(function($){ 
//Defines the delete button event binding
//Write inside to prevent global namespace contamination
function deltr(){ 
$(this).parents("tr").remove(); 
}; 
//A delete button already initializes the binding delete event
$("#table3 .del").click(deltr); 
//Add the line
$("#add3").click(function(){ 
$('<tr><td> The new line </td><td><button class="del"> delete </button></td></tr>') 
//Here the delete button is again bound to the event.
.find(".del").click(deltr).end() 
.appendTo($("#table3>tbody")); 
}); 
}); 

Solution # 2 - event bubbling

Using the event bubbling principle, we bind the event handler to the ancestor element of the button.
Then we can determine whether the event is triggered by the object we are looking for by the object event.target.
You can usually use DOM attributes such as event.target.classname, event.target.tagname, and so on.

<td><buttonclass="del"> delete </button></td> 

jQuery(function($){ 
//Delete button event binding for the fourth table
$("#table4").click(function(e) { 
if (e.target.className=="del"){ 
$(e.target).parents("tr").remove(); 
}; 
}); 
//Add button event binding for the fourth table
$("#add4").click(function(){ 
$("#table4>tbody").append('<tr><td> The new line </td><td><button class="del"> delete </button></td></tr>') 
}); 
}); 


Solution # 3 - copy the event method

The above options are relatively easy to implement even if you don't use the jQuery library. However, this solution is more dependent on jQuery. JQuery version 1.2 must be required. Lower-level jQuery requires plug-ins.
The above two schemes are to delete the function of a lot of brain, for a variety of trigger, binding. This scenario is different, and can be bound at domready as it would normally be for purely static elements. But when we add a new line we change it so that we don't want to concatenate strings to add a new line like we did above. This time we will try to use the method of copying DOM elements. And copy along with the bound events, and then modify the internal elements with things like find.
At the same time, just like this example, if you can delete all the elements, then the template is necessary, if you can't delete, then you don't need to use the template. To avoid being deleted by mistake, I have hidden the template here.
I'm using clone(true), which is a feature of jQuery
 
.template{display:none;} 

<trclass="template"> 
<td> Here is the template </td> 
<td><button class="del"> delete </button></td> 
</tr> 
<tr> 
<td> We already had it in this row </td> 
<td><button class="del"> delete </button></td> 
</tr> 
<tr> 
<td> We already had it in this row </td> 
<td><button class="del"> delete </button></td> 
</tr> 

jQuery(function($){ 
//Delete button event binding for the fifth table
$("#table5 .del").click(function() { 
$(this).parents("tr").remove(); 
}); 
//Add button event binding for the fifth table
$("#add5").click(function(){ 
$("#table5>tbody>tr:eq(0)") 
//Copied with events
.clone(true) 
//Remove template marks
.removeClass("template") 
//Modify internal elements
.find("td:eq(0)") 
.text(" The new line ") 
.end() 
//Insert table
.appendTo($("#table5>tbody")) 
}); 
}); 

Overall rating:

Each of the above four schemes has its advantages and disadvantages.
In scenario 0, the structure is not separated from the behavior at all, and the global namespace is polluted. Least recommended. So I don't even think of it as a plan. But for js beginners, it can be used for project rescue.
No. 1, the standard, nothing good, nothing bad
No. 2, this method gives full play to the advantages of js event bubbling. And the most efficient. But because this approach ignores jQuery's powerful selectors, it can be cumbersome to require too many element attributes. You will wander among the many if conditions of the right and wrong relationship. Then I remembered that I could use $(event.target).is(selector) in jQuery as a condition. This can greatly improve the efficiency of development, but slightly reduce the efficiency of execution.
Plan 3, which I think is the best way to think about the separation of structure and behavior. The downside is that it's too dependent on jQuery to write your own functions that replicate with events, which is obviously difficult for beginners. However, from the perspective of future trends, it is still recommended to use this scheme.

There is no definite number of specific schemes to choose. Depending on your project and your level of mastery of js and the idea of separation of structure and behavior. The most suitable is the best.

Additional:

Transform no. 3 into a perfect separation of structural behavior.
First, the element with a template is the template element. It is the source of all copies, and is made invisible to prevent them from being deleted by mistake. This template element is also optional if the light is not deleted. Because you can copy any existing loop element.
Second, add a repeat to each repeating element for the delete button to find that level of element. This is optional and sometimes not necessary.
Finally, add a class to each element that you want to modify to make it easier to find. For example, I have the content class here, and the new one can change the value inside.
Such a perfect case of separation of structure and behavior is completed.
 
<tableid="table6"> 
<tbody id="tbody6"> 
<tr class="template repeat"> 
<td class="content"> Here is the template </td> 
<td><button class="del"> delete </button></td> 
</tr> 
<tr class="repeat"> 
<td class="content"> We already had it in this row </td> 
<td><button class="del"> delete </button></td> 
</tr> 
<tr class="repeat"> 
<td class="content"> We already had it in this row </td> 
<td><button class="del"> delete </button></td> 
</tr> 
</tbody> 
<tfoot> 
<tr> 
<td> </td> 
<td><button id="add6"> add </button></td> 
</tr> 
</tfoot> 
</table> 

jQuery(function($){ 
//The delete button event binding for the sixth table
$("#tbody6 .del").click(function() { 
$(this).parents(".repeat").remove(); 
}); 
//Add button event binding for the sixth table
$("#add6").click(function(){ 
$("#tbody6>.template") 
//Copied with events
.clone(true) 
//Remove template marks
.removeClass("template") 
//Modify internal elements
.find(".content") 
.text(" The new line ") 
.end() 
//Insert table
.appendTo($("#tbody6")) 
}); 
}); 

Again, this section of js applies to the following HTML structure
 
<ulid="tbody6"> 
<li class="template repeat"> 
<span class="content"> Here is the template </span> 
<span><button class="del"> delete </button></span> 
</li> 
<li class="repeat"> 
<span class="content"> We already had it in this row </span> 
<span><button class="del"> delete </button></span> 
</li> 
<li class="repeat"> 
<span class="content"> We already had it in this row </span> 
<span><button class="del"> delete </button></span> 
</li> 
</ul> 

<script type="text/javascript"></script> 


Related articles: