1

I have a <td> that when I click on it, it shows me a alert with this message: clicked

My problem is when I append a new <td>, then when I click on it, I don't see any alert. Why? And how can I set event for appended elements?

Here is a fiddle that explains what I said.

HTML:

<table> <tr class = 'test'> <td> old </td> </tr> </table>
<br><br>
<div class ='addnewrow'>append new row</div>

CSS:

.addnewrow{
    border:2px solid;
    padding: 4px;
    text-align: center;
    cursor: pointer;
}

td{
    cursor: pointer;
}

JS:

$(".addnewrow").click(function(){
$("table").append('<tr><td>new</td></tr>');
});

$("td").click(function(){
alert('clicked');
});
Shafizadeh
  • 9,960
  • 12
  • 52
  • 89
  • The last function assigns click handlers to all td's that currently exist. If you add a td later, you will need to call that function again. – Mr Lister Sep 28 '15 at 21:32
  • Yea, its not showing because when you assign the click handler to the td elements, the td element you append doesn't exist yet. You attach the handler to all td elements again, but you may end up with duplicate handlers on previous td elements. You could attach the handler only to the new element, or you could attach 1 handler to the table and use bubbling to achieve what you'd like – frajk Sep 28 '15 at 21:35
  • @frajk thanks buddy. your explanation were useful. – Shafizadeh Sep 28 '15 at 21:41

1 Answers1

3

Use on to delegate the click events.

$("body").on("click","td",function(){
    alert('clicked');
});

This will take click events from elements whose parent is "body" and whose target is "td" and then use the callback function. This process of delegation inspects each click event and is done at the time of the event.

The click process you show in your question will only assign the event once, at the time of execution. As a result, only the "td" matches at that time will receive the event handler.

Another option you have, since you are creating these elements in script, is to assign the handler to them before they are appended to the page.

$(".addnewrow").click(function(){
    var row = $("<tr><td>new</td></tr>");
    $("td",row).click(function(){
        alert("clicked");
    });
    $("table").append(row);
});

It depends on what else is happening on the page which approach fits best.

Travis J
  • 81,153
  • 41
  • 202
  • 273
  • Worked correctly, thanks. +1 upvote for you. – Shafizadeh Sep 28 '15 at 21:37
  • This has been asked so many times before. You should close this as duplicate instead. – Felix Kling Sep 28 '15 at 21:41
  • @FelixKling - I don't carry around a book with these, and search here is too broken to constantly look up duplicates. It should be closed as a duplicate and was, but it is faster to me as a user to post something like this. I have this as finger tip knowledge, it was literally 2 minutes to type, as opposed to spending 5 making sure the duplicate target is accurate. Note also that even you have problems with this, as the choice you made for a duplicate was not the "canonical" or parent post for this type of situation. It took longer to review your comment's point than it did to answer this post – Travis J Sep 28 '15 at 21:46
  • @FelixKling - *meta is murder* – Travis J Sep 28 '15 at 21:47
  • 1
    @FelixKling - See also: http://stackoverflow.com/questions/203198/event-binding-on-dynamically-created-elements for a reference to what is generally the parent of these. Also note that your duplicate target included the comment "This is a possible duplicate" linking to the see also note I include here. – Travis J Sep 28 '15 at 21:50
  • @FelixKling - So far this has been 10 minutes of looking to the meta issue of a proper target of duplicate for this content. Hopefully the new examples feature that SO is rolling out will solve this type of problem for us, and examples can be used as duplicate targets for this situation. It will make it easier to have and maintain a place where content can be linked to without having to exhaustively search the currently duplicated environment in the "wild" here on SO main. – Travis J Sep 28 '15 at 21:51
  • I simply used the duplicate that someone already suggested. If you want this question to be closed as duplicate of the other one I'm happy to reopen this one. Yes finding the duplicates is a bit more work in the short term then writing an answer, but it helps keeping SO clean. By writing an answer instead you are contributing to the problem. Personally I use favorites to keep links to common duplicates... – Felix Kling Sep 28 '15 at 21:57
  • @FelixKling - Often I will find a duplicate. However, the time taken to compose this question also made the post quality enough to at least warrant a quick answer. Answers are in short supply lately, I am not sure that we need less overall. In the end, this is just a signpost as it is closed. I am not sure there is any evidence that would prove there is a problem right now with answering one off duplicate problems. Personally, I find no construct available to support saving me time with duplicate closure. I am not a janitor, I do not want to make my own janitorial tools. – Travis J Sep 28 '15 at 22:06