简体   繁体   中英

dynamically add clickable row to table

I'm trying to add rows to a table in HTML using JavaScript that are clickable.

Here is my codes:

HTML:

<table border="1" id="example" style="cursor: pointer;">
    <tr>
        <th>1</th>
        <th>2</th>
        <th>3</th>
        <th>4</th>
    </tr>
</table>

JavaScript:

//clicked function
$('#example').find('tr').click( function(){
    alert('You clicked row '+ ($(this).index()) );
});

//add new row
var x=document.getElementById('example');
var new_row = x.rows[0].cloneNode(true);                      
new_row.cells[0].innerHTML = "hello";
x.appendChild( new_row );

The problem is that the newly added rows are clickable but won't go through the clicked function to get the alert.

Anyone know why?

The problem is that the newly added rows are clickable but won't go through the clicked function to get the alert.

Anyone know why?

When you are executing the initial binding of the click event to your tr elements the event is only bound to the tr elements which exist at that time in the DOM.

That is how event binding works by default. You can only bind what is currently in the DOM.

However, using jQuery 1.7+'s on() or jQuery 1.6-'s delegate() methods you can bind event with delegation.

This allows you to bind the event to the closest static parent element of the element you actual want to delegate the event to.

I'm assuming the table itself is the closest static parent element, meaning it always exists and all you add dynamically is the tr elements.

Using on() when using jQuery 1.7+ would look similar to this:

$('#example').on('click', 'tr', function(){
    alert('You clicked row '+ ($(this).index()) );
});

Using delegate() when using jQuery 1.6- would look similar to this:

$('#example').delegate('tr', 'click' , function(){
    alert('You clicked row '+ ($(this).index()) );
});

What this will do is bind the event to the element with id of example but delegate the click to any tr clicked within that element. As the event is delegated each time, any newly added tr elements within #example will also be included.

Try this: Following code will take care of dynamically added rows.

//clicked function
$('#example').on('click', 'tr', function(){
    alert('You clicked row '+ ($(this).index()) );
});

You are binding your click event on document.ready. New elements added after wards wil not share this binding.

Yu can acheive what you are after by using .on()

$("body").on("click", "#example tr", function(event){
  alert('You clicked row '+ ($(this).index()) );
});

DEMO

is this what you are trying to achieve?

<table border="1" id="example" style="cursor: pointer;">
    <thead>
        <tr>
            <th>1</th>
            <th>2</th>
            <th>3</th>
            <th>4</th>
        </tr>
    </thead>
    <tbody id="addHere"></tbody>
</table>

var addHere = document.getElementById("addHere");
var newTr;
var newTd;

function clicked(evt) {
    alert("clicked tr: " + evt.target.parentNode.id);
}

for (var i = 1; i < 11; i += 1) {
    newTr = document.createElement("tr");
    newTr.id = "row" + i;
    newTr.addEventListener("click", clicked, false);

    for (j = 1; j < 5; j += 1) {
        newTd = document.createElement("td");
        newTd.textContent = j;
        newTr.appendChild(newTd);
    }

    addHere.appendChild(newTr);
}

on jsfiddle

In your code it seems that you are looking for rows and then bind an event to any that you find.

You then proceed to add rows using Node.cloneNode

Cloning a node copies all of its attributes and their values, including intrinsic (in–line) listeners. It does not copy event listeners added using addEventListener() or those assigned to element properties (eg node.onclick = fn).

so there are no event handlers bound to any of these newly added elements.

Another way to deal with this would be to use jquery delegate event handler method (on)

When a selector is provided, the event handler is referred to as delegated. The handler is not called when the event occurs directly on the bound element, but only for descendants (inner elements) that match the selector. jQuery bubbles the event from the event target up to the element where the handler is attached (ie, innermost to outermost element) and runs the handler for any elements along that path matching the selector.

and do the following.

var addHere = document.getElementById("addHere");
var newTr;
var newTd;

function clicked(evt) {
    alert("clicked tr: " + evt.target.parentNode.id);
}

$(document).on("click", "#addHere tr", clicked);

for (var i = 1; i < 11; i += 1) {
    newTr = document.createElement("tr");
    newTr.id = "row" + i;

    for (j = 1; j < 5; j += 1) {
        newTd = document.createElement("td");
        newTd.textContent = j;
        newTr.appendChild(newTd);
    }

    addHere.appendChild(newTr);
}

on jsfiddle

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM