Dev
Dev

Reputation: 153

JQuery - Row click event won't fire on newly added table rows

Question Background:

I have a table in a View that is dynamically populated from a database. Filters in the View allow the user to select data which in-turn needs to be displayed on the table. The re-adding of the data is achieved through deleting the current table rows then adding the new data in its place.

The Issue:

On each table row I have the ability to click the row which renders data in a Modal pop-up, each time a user changes the filter list the database is re-queried, which requires the table data to be removed then repopulated. The newly added rows are not triggering the row click event when selected.

The code:

The table is populated in the View as follows:

@foreach (var component in @Model.ComponentDetailsList)
{
    <script>

        var codebase = '@component.Codebase';
        var component = '@component.ComponentName';
        var tfsLocation = '@component.ComponentDevTfsLocation';
        var tfsQaLocation = '@component.ComponentQaTfsLocation';

        AddRows(codebase, component, tfsLocation, tfsQaLocation);
    </script>
}

The JQuery method AddRows:

    function AddRows(codebase, component, tfsLocation, tfsQaLocation) {

    $html = '<tr><td id="codebaseCell"><b>' + codebase + '</b></td><td  id="componentCell">' + component + '</td><td class="hidden-xs hidden-sm" id="tfsDevCell">' + tfsLocation + '</td><td class="hidden-xs hidden-sm" id="tfsQaCell">' + tfsQaLocation + '</td><td><button type="button" class="btn btn-danger pull-left" id="deleteQueuedComponent">Delete</button></td></tr>';

    $("#componentTable tbody").append($html);
};

The Row On-Click event:

$(document).ready(function () {

$('#componentTable tr').click(function () {

var tfsCodebase = $(this).find('#codebaseCell').text();

alert(tfsCodebase);

var tfsComponent = $(this).find('#componentCell').text();

$.ajax({
    url: "/Release/GetComponentFiles",
    data: { codeBase: tfsCodebase, component: tfsComponent },
    success: function (component) {

        var count = 0;

        var componentName = component.componentName;

        var componentCodeBase = component.componentCodebase;

        for (var item in component.fileList) {

            var devItem = component.componentDevTfsLocation + '/' + component.fileList[item];

            var qaItem = component.componentQaTfsLocation + '/' + component.fileList[item];

            count++;

            AddRowsToModal(componentName, componentCodeBase, component.fileList[item], devItem, qaItem, count);
        }

        document.getElementById("modalInfo").innerText = 'Queued Files For: ' + component.componentName;

        $("#componentModal").modal('show');
    }
});
});
});

The function that is called when a filter item is clicked. The ClearTableAndAddRows function deletes the table contents and re-adds it but as stated the row click event handler will no longer work:

 $(document).ready(function () {

    $("#codebaseNameList li").click(function () {
        var codebase = $(this).text();

        $.ajax({
            url: "/Release/QueryComponentsByCodebase",
            data: { codebase: codebase },
            success: function (component) {

                for (var item in component.codebaseList)
                {
                    ClearTableAndAddRows(component.codebaseList[item].Codebase, component.codebaseList[item].ComponentName, component.codebaseList[item].ComponentDevTfsLocation, component.codebaseList[item].ComponentQaTfsLocation);

                    AddRowsToComponentList(component.codebaseList[item].ComponentName);

                }
            }
        });
    });
    });

The JQuery method ClearTableAndAddRows used to delete, then re-add the new rows to the existing table body:

function ClearTableAndAddRows(codebase, component, tfsLocation, tfsQaLocation) {

$("#queuedFilesTable").empty();

$htmlFilteredRow = '<tr><td id="codebaseCell"><b>' + codebase + '</b></td><td id="componentCell">' + component + '</td><td class="hidden-xs hidden-sm" id="tfsDevCell">' + tfsLocation + '</td><td class="hidden-xs hidden-sm" id="tfsQaCell">' + tfsQaLocation + '</td><td><button type="button" class="btn btn-danger pull-left" id="deleteQueuedComponent">Delete</button></td></tr>';

$("#componentTable tbody").append($htmlFilteredRow);
};

Upvotes: 0

Views: 1845

Answers (2)

freethinker
freethinker

Reputation: 2435

Ok. Your click event not fire because you change your HTML dynamically. $(document).ready() is fire after DOM ready and you bind events BEFORE you adding new table elements to your HTML. To resolve this problem, bind your click events after this action $("#componentTable tbody").append($html);Or use .on('click' ... instead of .click(

Upvotes: 0

Satpal
Satpal

Reputation: 133453

Event handlers are bound only to the currently selected elements; they must exist on the page at the time your code makes the event binding call.

You need to use Event Delegation using .on() delegated-events approach dynamically added elements.

$('#componentTable').on('click','tr', function () {
   //Your code
});

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.

Upvotes: 1

Related Questions