简体   繁体   English

如何检测DataTable子行内的按钮单击事件?

[英]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.我有标准的 DataTable 代码,它填充数据表并在行点击时显示子行。 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.在子行内(使用格式功能),我添加了一个按钮,我想在单击它时执行某些操作,但是每次单击该按钮(数据表包含新 tr->td 内的子行)时,td 单击事件用于打开/关闭子行的函数被触发,并且我在格式函数中为d[]数组收到"Uncaught TypeError: Cannot read property '0' of undefined"

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?有没有办法防止为子行触发 td click事件或以某种方式检测按钮单击? 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.将单击处理程序添加到按钮并从处理程序返回false以防止默认操作并阻止事件传播到父元素。 Alternatively you may call stopPropagation() and preventDefault() .或者,您可以调用stopPropagation()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 .最好删除id='joinbutton'并改用类名,例如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.有关代码和演示,请参阅此 jsFiddle

I resolve my problem with @gaemaf solution:我用@gaemaf 解决方案解决了我的问题:

// 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");
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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