Bind events to dynamically created elements using jQuery

While writing code in jQuery, we sometimes need to create HTML elements dynamically. But the problems starts occurring when the events that we have already binded to the existing HTML elements, does not works in the same way for the newly created elements. So, lets say we have existing DIV and we have a click event binded to it. Now, when we click on this DIV, we get an alert. After that, we add one more DIV to the page dynamically, but on clicking on this new DIV there is no alert coming. So, what is the problem here? Why is the click event not working for this new DIV? Let’s look into this problem in details.

HTML markup:
For this demo, we will be using a simple HTML markup, like this:

<button id="myButton">Add New Row</button>
<table id="myTable">
    <tr>
        <td>This is a static row.</td>
    </tr>
</table>

Create Elements Dynamically:
In the HTML markup, we have a simple button and a table. The table already have a row and we will add some more rows to it dynamically. So, lets first add some rows dynamically here using the code below.

$("#myButton").click(function () {
    var newRow = '<tr><td>This is a dynamically added row.</td></tr>';
    $('#myTable tr:last').after(newRow);
});

Explanation:

  1. Code in the first line
    $("#myButton").click(function () {
    

    Here, we are binding a click event handler to  myButton . Now if we click on this element, then the code below will be executed.

  2. Code in the second line
    var newRow = '<tr><td>This is a dynamically added row.</td></tr>';
    

    This code is used to set a variable named  newRow . This variable is HTML string which we are going to insert. Here, it is a table row, inside it we have a table cell having some dummy text for the demo.

  3. Code in the third line
    $('#myTable tr:last').after(newRow);
    

    Here, the selector #myTable tr:last will go to the table with ID as #myTable and then it will find the last table row inside the table using the :last Selector. Now, we will insert the new content in DOM as we have specified in the HTML string named  newRow after the last row using the .after() method. Here, I am using the .after() method because it serves my purpose best in the current scenario. You can use any of the DOM Insertion Inside or Outside methods based on your requirement.

Bind Click Event to HTML Elements:
Now we are going to bind the click event to all the table rows, hoping that it would work for both the existing and the newly created ones, using the code below.

$("#myTable tr").click(function () {
    $(this).toggleClass('myClass');
});

Explanation:

  1. Code in the first line
    $("#myTable tr").click(function () {
    

    Here, we are binding a click event handler to all the table rows inside the table myTable using the selector #myTable tr .

  2. Code in the second line
    $(this).toggleClass('myClass');
    

    Here, we are getting the clicked row jQuery object using $(this) and then we are toggling (adding or removing) a class named myClass using the .toggleClass() method. Now if the table row being clicked in the current scope already has the class, then it will be removed; if table row does not have the class, then it will be added.

and the myClass CSS:

.myClass {
    background-color:lightgreen;
}

Issue With This Approach:
Now, we are able to create elements dynamically and have binded the click event to all the table rows. Our expected result is, when we click on any of the rows, whether the existing or the newly created ones, a class named myClass will be added to the row and its background color will turn ‘lightgreen’ as specified in the myClass CSS above.

You can have a look at the issue here:  Demo on jsFiddle #1
( Firstly, click on the ‘Add New Row’ button to add some new rows dynamically and then click on the ‘static’ and the ‘dynamic’ rows to see the issue. You will see the click event working for the ‘static’ one only but not for the ‘dynamic’ ones. )
Now, this happens since the click event handler here is bound only to the currently selected elements and only to those elements that exist on the page at the time our code made the call to .click() . Hence, it does not works for the dynamic rows, since they were added to the page at a later time.

Bind Click Event to Dynamically Created Elements:
Now, this is how we are going to resolve this issue. We will use Event Delegation to register the click event handler to the dynamically created rows using the below code:

$('#myTable').on('click', 'tr', function (event) {
    $(this).toggleClass('myClass');
});

In this delegated-events approach, the handler is not called when the click event occurs directly on the myTable table element, but only for table rows (descendants/inner elements). The delegated events have the advantage that they can process events from descendant elements that are added to the document at a later time. By picking an element that is guaranteed to be present at the time the delegated event handler is attached, we can use delegated events to bind the click event to dynamically created elements and also to avoid the need to frequently attach and remove event handlers.

Demo:

  • Working Demo on jsFiddle #2
    ( Firstly, click on the ‘Add New Row’ button to add some new rows dynamically and then click on the ‘static’ and the ‘dynamic’ rows to see the click event working for both the ‘static’ & the ‘dynamic’ ones. )

That’s it! 😉 If you have any comments or suggestion or any queries about this post please add it in comments section. I would really appreciate it.

Happy Coding 🙂

Advertisements

50 thoughts on “Bind events to dynamically created elements using jQuery

  1. use .on to bind events to dynamically created element.
    $(“#ID”).on(“click”, “ID/class”, function(){
    //write your logic inside that
    });

    • First of all, thanks so much for the response. Secondly, I totally agree with you about the use of .on() method here and if you have a close look I am already using the delegated-events approach as you have mentioned. You can also see it in the second demo too 🙂

  2. Pingback: Get element on which currently called jQuery event handler is attached | jQuery Tips and Tricks

  3. Ive been trying to solve this problem for two days. I ran across this article and everything started working. Thank You!

  4. What if your dynamically added item is a div with an anchor… and you are trying to select the anchor? I’m trying:

    $(‘.airport-area’).on(‘click’, ‘.airport > a’, function (event) {
    $(event).preventDefault;
    });

    but it’s not working.

    • Hi @whiskeym1ke. Could you please recreate your issue on jsFiddle and post the link here (Please don’t post the whole code. Try to keep the js code and the HTML markup to the minimal ;)). It would really help me to get a clear picture of your issue and provide you a better solution. Also, please explain what you mean by it’s not working. Is the alert inside the event handler not coming or else. Looking forward to your response 🙂

      • I’m afraid with all the HTML being spread over numerous views, and PHP loops through data… that would be too much work right now. I’m trying to focus all my time/effort on the problem at hand. Thank you anyhow!

  5. Thanks so much for this article – I was pulling my hair out for 2 hours running through Stack Overflow and then I came across your post 🙂 Perfect!

    • Hi Adam,

      Thanks so much for your response. Glad that jsFiddle demo help you. You can also look into my other blogs on jQuery as well, if you like 🙂

      Thanks,
      Palash

  6. Hi,
    I have 2 arrays which needs to listed into dropdown.

    array1 = Array([0]=>1,[1]=>2);
    array2 = Array ( [0] => Array ( [0] => A, [1] => B ) [1] => Array ( [0] => X, [1] => Y) );

    The second dropdown should be controlled via what i select from first dropdown list.
    ie, if i select “1” from first dropdown list, the second dropwon list should show only “A”,”B” and
    if i select “2” from first dropdown list, the second dropwon list should show only “X”,”Y”, removing the earlier listed values i.e “A” & “B”.

    Also i will adding both these dropdown boxes dynamically as and when required. I should be able to change list in the dynamically added elements accordingly.

    Can anyone let know haw this can be achieved..

    • Hi Karthik,

      Thanks so much for your response. Could you please post a functional example that illustrates your problem on jsFiddle. I could then provide you with some solution to your issue.

      Thanks,
      Palash

  7. Hi Palash,

    Sorry for the delay. I have created example. please refer link http://jsfiddle.net/LQ3WF/
    Though i am not expert in JQuery, i have been referring to some examples and tried to achieve what i needed.

    But the problem now is when i change first dropdown i want the second dropdown to be blank, and then on change only third dropdown should load/refresh.

    Please let know if improvements can be done.

    Regards
    Karthik

  8. Hi, i have a query that, if I change the row data onclick of edit button and I do not save that data and click on cancel button. How can I reload the previous data on click of cancel button of that particular row.

    • Hi Uttara,

      Thanks so much for your response. Regarding your question, you can store the previous data using the jQuery .data() method while changing the row data and while clicking on the cancel button, you can restore the data we had saved previously. I hope that makes sense. Let me know if you have further queries. 🙂

      Thanks,
      Palash

  9. Thank you so much this problem is sort out.
    I have another query that How can I use next() method of jquery to find the next checkboxes on click of one checkbox and make the next all checkboxes uncheck.
    Please give me some help about this question as early as possible.
    Thank you so much.

  10. Hi…
    I have one question…
    I have a table to load data, but if rows more than 500 then it takes too much time. For that I have use web grid control. After showing data in web grid I want to post that data and save into the db. But the problem is that I am not getting data of the web grid. We can take form data directly by writing form.serialize() but in case of web grid its not working.
    Can you please help me?
    Its very urgent.
    Please reply me as early as possible.
    Thank you

  11. Hi, i am working on same functionality but with onchange event i am able to create a row at particular location in a table onchange of event but not able to remove the row onchange
    $(‘#myTable > tr’).eq(k).remove(); //removing code
    var newRow = ‘This is a dynamically added row.’;
    $(‘#myTable > tbody > tr’).eq(k).after(newRow); // adding row

    sample code is attached i am using for loop to create the no of ros selected by user but its adding new row on chnage of input without deleting rows.I’ve to delete the rows ddynamically.

  12. Thanks for this, was trying to create a table that added a row whenever the last row in the table was clicked. Your code got me to where I wanted, thank you.
    My code –
    $( ‘#classNumbers’ ).on(‘click’, ‘tr:last’, function(event) {
    $(‘#classNumbers tr:last’).after(”);
    });

  13. html tags are not printing…
    $(document).ready(function(){
    $(‘tbody’).on(‘click’,’a.disNgen’, function () {
    var dng = $(‘a.disNgen’).attr(‘data_val’);
    /////getting value of first anchor tag only////////
    alert (dng);//////here///

    disNgen is class define in anchor tag
    data_val is an attribute in anchor tag
    tbody is table body where the dynamically created anchor tag is.

    • Hi Amitabh,

      Thanks so much for your response. Could you please post a functional example that illustrates your problem on jsFiddle. I could then provide you with some solution to your issue.

      Thanks,
      Palash

  14. Hi,
    I am completely new to JQuery.And i was facing similar issue with highlighting dynamic rows.I tried the onclick code which u gave,but it doesnt seem to work for me.Just wanted to know if i give a class tag inside the Jquery like $(“.classname”).on(‘click’…),will it not work?

    Also,i tried giving the id and working,,but still no luck!!

  15. I’m adding select tag dynamically. when I click the #mySelect0 it dynamically displays #mySelect1. But the event delegation is not working for #mySelect1 which is to display #mySelect2. Here is the event code:

    $(“#mySelect0”).change(function() { //dropdown name
    row = table.insertRow(1);
    cnt++;
    displayDropList(); //dynamically adds select
    displayText();
    $(‘#mySelect0’).on(‘click’, ‘#mySelect1’, function(){
    alert(‘ajas’); //not displaying this one
    });

    });

    $(“#mySelect1”).change(function() { //dropdown name
    alert(“hey”); //nothing works here
    row = table.insertRow(2);
    cnt++;
    displayDropList(); //not working
    displayText(); //not working
    });

    • Hi George,

      Thanks so much for your response. Could you please post a functional example that illustrates your problem on jsFiddle. I could then provide you with some solution to your issue.

      Thanks,
      Palash

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s