【问题标题】:How to detect button click event inside DataTable child row?如何检测 DataTable 子行内的按钮单击事件?
【发布时间】:2016-02-13 11:30:56
【问题描述】:

我有标准的 DataTable 代码,它填充数据表并在行点击时显示子行。 在子行内(使用格式功能)我添加了一个按钮,我想在点击它时做一些事情,但每次我点击按钮(数据表包含新的 tr->td 内的子行)td 点击事件用于打开/关闭子行的函数被触发,我得到 "Uncaught TypeError: Cannot read property '0' of undefined" 格式函数中的 d[] 数组。

这是子行打开/关闭的代码:

$('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>';

}

有没有办法防止 td click 事件被触发子行或以某种方式检测按钮单击? 谢谢

【问题讨论】:

  • 你可以将事件添加到你的函数 $('tbody').on('click', 'td', function(e) { 这样你就可以测试 e.target 元素,如果这不是正确的,您可能会停止您的功能,或者您可能会处理事件 stoppropagation
  • 太复杂了,无法在同一个函数中创建两个函数,所以我将表格的按钮提取到一个 td 中。感谢您的帮助,我稍后可能会回复您的答案
  • 您能否提供完整的示例,例如使用 JSFiddle,这将更容易理解确切的问题。同时你可以尝试添加 event.stopPropagation();内部按钮点击事件。

标签: javascript jquery datatables


【解决方案1】:

我在我的评论之后提出了 sn-p(请参阅 cmets,而不是格式函数中的那些,它们是我使 sn-p 运行所必需的):

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>

【讨论】:

    【解决方案2】:

    我用@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");
    });
    

    【讨论】:

      【解决方案3】:

      解决方案

      将点击处理程序添加到按钮并从处理程序返回false,以防止默认操作并阻止事件传播到父元素。或者,您也可以致电stopPropagation()preventDefault()

      $('#example tbody').on('click', 'button', function (e) {
      
         // ... skipped ...
      
         return false;
      });
      

      最好删除id='joinbutton' 并改用类名,例如btn-join。然后你就可以使用下面的代码来定位特定的按钮了。

      $('#example tbody').on('click', '.btn-join', function (e) {
      
         // ... skipped ...
      
         return false;
      });
      

      演示

      有关代码和演示,请参阅this jsFiddle

      【讨论】:

      • 返回 false 不会阻止事件冒泡。看下面的简单例子
      • @NitinGarg,查看演示,其中按钮的单击事件不会导致调用其他处理程序。
      • 亲爱的,请给我几分钟的时间来分析演示。
      • @NitinGarg,你的说法不正确。 jQuery 事件处理程序与通过onclick 属性附加的处理程序不同,请参阅on()从事件处理程序返回 false 将自动调用 event.stopPropagation()event.preventDefault()
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-07-28
      • 1970-01-01
      • 2015-04-25
      • 2018-10-21
      • 2021-04-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多