Josh
Josh

Reputation: 618

Jquery .on() either not working or firing twice

So not sure exactly what's going on but can make a few guesses.

My understanding of .on() is that it is meant to attach to all dynamically added elements. But it doesn't seem to be working here. Or if I've misunderstood that, then the way I'm implementing is not working.

On document load, I call this:

$("#orderBox tbody tr").on( 'click', function ( e ) {
    selectRow($(this));
} )

Where selectRow() toggles the class on a tr element (code below).

When the document is loaded, the table is empty, so new rows are added by the addTableRow() function, which just appends a tr to the tbody. Once that tr has been added, clicking it does nothing. So I moved the .on() event from document load to after the new row has been created.

function redrawOrderBox(){
    $("#orderBox tbody tr").on( 'click', function ( e ) {
        selectRow($(this));
    } )
}

function selectRow(row){
    row.toggleClass('selected');
}

function addTableRow(items){

    newRow = "<tr>";
    newRow += "<td class=\"hide\">"+items[0]+"</td>"
    newRow += "<td>"+items[1]+"</td>"
    newRow += "<td>"+items[2]+"</td>"
    newRow += "<td>"+items[3]+"</td>"
    newRow += "<td>"+items[4]+"</td>"
    newRow += "<td class=\"hide\">"+items[5]+"</td>"
    newRow += "<td class=\"hide\">"+items[6]+"</td>"
    newRow += "<td class=\"hide\">"+items[7]+"</td></tr>";
        
    $('#orderBox tbody').append(newRow);
    redrawOrderBox();
}

This kinda works. The class "successfully" toggles on it seems every second row. After adding three rows, from what I can tell in inspector or when sticking in an alert(), it fires successfully on the third row, then fires twice on the second row when clicked (giving the appearance that nothing happened). On the first row, it fires three times, which gives the impression that it worked fine.

So I'm calling the click event multiple times - probably because I'm attaching it 3 times.But if I try to use it in document load, nothing happens.

What I intend to do is modify the redraw() function to strip the click event before reattaching it. But it just feels like the wrong way to go about it.

What's the best way to do this?

Upvotes: 3

Views: 36

Answers (1)

Jon P
Jon P

Reputation: 19802

For jquery on, you effectively need 2 selectors, the parent and the child. You attatch on to the parent with a parameter as a selector to determine decendants that fire the event.

Use this instead:

$("#orderBox tbody").on( 'click', 'tr', function ( e ) {
    selectRow($(this));
} )

Existing trs and those added dynamically will now correctly fire the event handler.

Upvotes: 3

Related Questions