简体   繁体   中英

How to detect button click event inside DataTable child row?

I have the standard DataTable code which populates the datatable and shows child rows on row clicks. Inside the child row (using the format function) i have added a button and i want to do something when it's clicked but each time i click the button(data table contains child row inside a new tr->td) the event of td click which is used to open/close child rows is fired and i get "Uncaught TypeError: Cannot read property '0' of undefined" for the d[] array in format function.

This is the code for the child rows open/close:

$('tbody').on('click', 'td', function() {
    var tr = $(this).closest('tr');
    id = $(this).closest('table').attr('id');
    table = $('#' + id).DataTable();
    var row = table.row(tr);
    if (row.child.isShown()) {
        // This row is already open - close it
        row.child.hide();
        tr.removeClass('shown');
    } else {
        // Open this row
        row.child(format(row.data(), id)).show();
        tr.addClass('shown');
    }
});

function format(d, id) {
// `d` is the original data object for the row
if(sessionStorage['name']!=undefined)
    return '<img src="images/photo.jpg" id="photo" />' + '<p>Session created by:' + d[0] + '</p>' + '<p>Start Date:' + d.start_date + '</p>' + '<p>Extra info:' + d[3] + '</p>' + "<button class='btn btn-default' id='joinbutton' role='button'>Join Session</button>";
else
return '<div>' + '<img src="images/photo.jpg" id="photo" />' + '<p>Session created by:' + d[0] + '</p>' + '<p>Start Date:' + d.start_date + '</p>' + '<p>Extra info:' + d[3] + '</p>' + '</div>';

}

Is there a way to either prevent the td click event from being fired for child rows or to detect the button click somehow? Thanks

I propose the snippet following my remark (see the comments, not those in the format function, they are required for me to make the snippet running):

 function format(d, id) { // `d` is the original data object for the row //if(sessionStorage['name']!=undefined) return '<img src="http://icons.iconarchive.com/icons/treetog/junior/256/image-format-jpg-icon.png" id="photo" />' + '<p>Session created by:' + d[0] + '</p>' + '<p>Start Date:' + d.start_date + '</p>' + '<p>Extra info:' + d[3] + '</p>' + "<button class='btn btn-default' id='joinbutton' role='button'>Join Session</button>"; //else //return '<div>' + '<img src="images/photo.jpg" id="photo" />' + '<p>Session created by:' + d[0] + '</p>' + '<p>Start Date:' + d.start_date + '</p>' + '<p>Extra info:' + d[3] + '</p>' + '</div>'; } // to handle the joinbutton created dynamically you need: // avoid to use the same ID for more than one element $(document).on('click', 'button[role="button"]', function(e) { alert('This is the button'); }); $(function () { $('tbody').on('click', 'td', function(e) { // to avoid to receive the button click inside the td you need: if ($(e.target).is(':not(td)')) { alert('This is inside td'); return; } var tr = $(this).closest('tr'); id = $(this).closest('table').attr('id'); table = $('#' + id).DataTable(); var row = table.row(tr); if (row.child.isShown()) { // This row is already open - close it row.child.hide(); tr.removeClass('shown'); } else { // Open this row row.child(format(row.data(), id)).show(); tr.addClass('shown'); } }); });
 table, th, td { border: 1px solid black; border-collapse: collapse; } th, td { padding: 10px; }
 <link href="http://code.jquery.com/ui/1.11.3/themes/smoothness/jquery-ui.css" rel="stylesheet"/> <script src="http://code.jquery.com/jquery-1.11.3.min.js"></script> <script src="http://code.jquery.com/ui/1.11.3/jquery-ui.js"></script> <link href="//cdn.datatables.net/1.10.11/css/jquery.dataTables.min.css" rel="stylesheet"> <script src="//cdn.datatables.net/1.10.11/js/jquery.dataTables.min.js"></script> <table id="tblId"> <thead> <tr> <th>Month</th> <th>Savings</th> </tr> </thead> <tfoot> <tr> <td>Sum</td> <td>$180</td> </tr> </tfoot> <tbody> <tr> <td>January</td> <td>$100</td> </tr> <tr> <td>February</td> <td>$80</td> </tr> </tbody> </table>

SOLUTION

Add click handler to the button and return false from the handler to prevent default action and stop the event from propagating to parent element. Alternatively you may call stopPropagation() and preventDefault() .

$('#example tbody').on('click', 'button', function (e) {

   // ... skipped ...

   return false;
});

It would be better to remove id='joinbutton' and use class name instead, for example btn-join . Then you would be able to target specific button with the code below.

$('#example tbody').on('click', '.btn-join', function (e) {

   // ... skipped ...

   return false;
});

DEMO

See this jsFiddle for code and demonstration.

I resolve my problem with @gaemaf solution:

// Handle click on checkbox
$("#example tbody").on("click", 'input[type="checkbox"]', function(e){
    var $row = $(this).closest("tr");

    if(this.checked){
        $row.addClass("active");
    } else {
        $row.removeClass("active");
    }

    // Prevent click event from propagating to parent
    e.stopPropagation();
});

// Handle click on table cells
$("#example tbody").on("click", "td", function(e){
    // Begin Solution
    if ($(e.target).is(':not(td)')) {
        return;
    }
    // End solution
    $(this).parent().find('input[type="checkbox"]').trigger("click");
});

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