Monday, January 3, 2011

jQuery : Binding events to dynamic DOM elements

Today in this blog post am going to discuss about a simple way of binding events to a DOM structure, especially one that changes dynamically.

Binding events to jQuery is simple. All that you need to do is use the bind function to bind a DOM element to a given event or to use the various alias functions like click, dblclick etc etc.

One of the major advantages that jQuery offers is the easy manipulation of DOM objects. That means, you can easily create, add or delete DOM elements on the fly and insert them into the page. However, doing this has its quirks as well when it comes to event binding. Lets take an example.

Consider the following HTML snippet in your page.

1_c1
1_c2
2_c1
2_c2


Let us assume that I want to add a sibling div to the div with class "parent2" whenever a child is clicked upon. Doing that is very simple. Here's how I would do it initially.

$(".child").click(function(){
     var newSibling = '
new_child
'; $(this).parent().append(newSibling); });

Well, that solves our purpose. But there is one small problem. As you see, the new div that i inserted into the DOM has a class attribute with a value "child". So, i should presumably expect that if the user clicks over the newly inserted div element, the click event handler should be triggered. Unfortunately for us, that does no happen.

It seems like the event handlers are bound to the DOM elements statically. i.e. Once the DOM is built, the selectors do not bind the same event handlers to newly introduced elements.

Now that poses a serious problem, because conceptually, it seems like the events should have been bound. So, how do we go about it?

Event bubbling to the rescue!

We know well that events in javascript are bubbled upwards in the DOM structure. This feature enables us to solve the problem of event binding for dynamically created elements.

What we are going to do is to bind the click event handler to the parent div of the "child" elements. So, whenever a child element is clicked upon, the parent div gets notified due to event bubbling. In the click handler, you can identify the source DOM element that was clicked by using the value of event.target, where event is the argument that is passed to the click handler. Once we have got a handle on the source DOM element, the job's done! So, if you add a new DOM element to the parent, since the click handler is bound to the parent, you can always be sure that the new child element will also be clickable because the actual handler function is on the parent element.

Here is the code.

$(".parent1").click(function(event){
     var $source = $(event.target);
     var newSibling = '
new_child
'; $($source).parent().append(newSibling); });

Pretty simple eh? Ya, I know its a dumb example, but, I guess simple is always better for demonstration purposes.

Oh, and I could have used $(this).append(newSibling); instead of $($source).parent().append(newSibling);, because it suits our requirement, but I was just trying to be a bit verbose!

Thats all for now folks!

Happy Programming :)
Signing Off
Ryan

1 comment:

Anonymous said...

So this is a year old now, but since i ran across it i figure i would leave this for you and future googlers:

$('.parent1, .parent2').delegate('.child', 'click', function (e){
var $this = $(this),
$clone = $this.clone();
$this.parent().append($clone);
});