响应式jQuery DataTables无法从子行单元格获取行索引
问题
我有一个带输入字段的jQuery DataTables,需要在用户输入时获取对应行号。之前的方案在表格正常显示时有效,但开启响应式模式后,当输入字段进入子行弹窗,获取行索引的代码返回undefined。
相关代码如下:
JavaScript代码
function drawInput(data, type, row, meta) { return '<input id="r' + meta.row + 'c' + meta.col + '" val="' + data + '"></input>'; } var data = [{ c1: 'r1c1', c2: 'r1c2', c3: 'r1c3' }, { c1: 'r2c1', c2: 'r2c2', c3: 'r2c3' }]; $(function() { var table = $('table').dataTable({ info: false, searching: false, ordering: false, paging: false, columns: [{ defaultContent: '<span></span>' }, { data: 'c1', name: 'c1', defaultContent: '<input></input>', render: drawInput }, { data: 'c2', name: 'c2', defaultContent: '<input></input>', render: drawInput }, { data: 'c3', name: 'c3', defaultContent: '<input></input>', render: drawInput } ] }); table.api().rows.add(data); table.api().draw(); $('body').on('change', 'table :input', function(e) { // Find the row that contains the input field //console.log(this); var row = table.api().row($(this).closest('td')); // Show the row index - result is undefined! Why? console.log(row.index()); }); });
HTML代码
<link href="https://cdn.datatables.net/1.13.6/css/jquery.dataTables.min.css" rel="stylesheet" type="text/css" /> <link href="https://cdn.datatables.net/responsive/2.5.0/css/responsive.dataTables.min.css" rel="stylesheet" type="text/css" /> <script src="https://code.jquery.com/jquery-3.7.0.min.js"></script> <script src="https://cdn.datatables.net/1.13.6/js/jquery.dataTables.min.js"></script> <script src="https://cdn.datatables.net/responsive/2.5.0/js/dataTables.responsive.min.js"></script> <div style='width:150px;'> <table width="100%" class="responsive"> <thead> <tr> <th></th> <th>Col 1</th> <th>Col 2</th> <th>Col 3</th> </tr> </thead> <tbody> </table> </div>
解决方案
问题核心是响应式模式下,子行的DOM结构和主行是兄弟关系而非父子关系,原代码的closest('td')无法关联到主行节点。以下两种方案可解决:
方案一:通过DOM结构定位主行
修改事件处理逻辑,先找到子行容器,再定位到对应的主行:
$('body').on('change', 'table :input', function(e) { // 定位到响应式子行,再获取其前一个兄弟节点(即主行) var $mainRow = $(this).closest('tr.dtr-details').prev('tr'); var row = table.api().row($mainRow); console.log(row.index()); });
方案二:渲染时绑定行索引到元素属性
直接在输入字段渲染时,把行索引存入元素的自定义属性,后续直接读取:
- 修改
drawInput函数:
function drawInput(data, type, row, meta) { // 添加data-row-index属性存储行索引 return '<input id="r' + meta.row + 'c' + meta.col + '" val="' + data + '" data-row-index="' + meta.row + '"></input>'; }
- 修改事件处理代码:
$('body').on('change', 'table :input', function(e) { // 直接读取自定义属性中的行索引 console.log($(this).data('row-index')); });
原因说明
响应式模式下,隐藏列的内容会被渲染到带dtr-details类的子行中,这个子行是主行的下一个兄弟节点,而非子节点。原代码通过closest('td')找不到主行的<td>元素,导致row.index()返回undefined。两种方案分别通过DOM关联、预存索引的方式,绕过了响应式DOM结构的限制。
内容的提问来源于stack exchange,提问作者Nikki Locke
相关产品推荐
相关产品推荐

