三级层级DataTable子行点击无法展开孙行的修复咨询
三级层级表格展开问题修复方案
问题说明
我编写了一套逻辑实现三级层级表格(数据结构为一级→二级→三级),能正常生成表格结构,但点击二级表格(child-table)的行时,无法展开对应的三级表格(grand-child table),求修复方案或替代实现方式。
示例数据
example_data = [ { "Approved": 0, "Denied": 1, "tat_avg": 0, "Name": "Total Care- PREFERRED", "Aetna": { "Approved": 0, "Denied": 1, "tat_avg": 0, "Name": "Aetna", "Humira": { "Approved": 0, "Denied": 1, "tat_avg": 0, "Name": "Humira" } } }, { "Approved": 1, "Denied": 0, "tat_avg": 0, "Name": "Acaria Specialty Pharmacy", "test bin": { "Approved": 1, "Denied": 0, "tat_avg": 0, "Name": "test bin", "Aveed": { "Approved": 1, "Denied": 0, "tat_avg": 0, "Name": "Aveed" } } }, ]
原实现代码
$.ajax({ url: "{{ path('api_path') }}", method: 'GET', dataType: 'json', data: {enterpriseID:{{user.enterpriseID}}, tab: 'pharmacy_analysis', start: startdate, end: enddate}, success: function (data) { pharmacy_analysis_data = example_data; // Destroy the existing DataTable if it already exists if ($.fn.DataTable.isDataTable('#example1')) { $('#example1').DataTable().destroy(); } // Initialize DataTable with new data let table1 = $('#example1').DataTable({ data: pharmacy_analysis_data, scrollY: 500, paging: false, columns: [ { data: null, className: 'dt-control', orderable: false, defaultContent: '', }, { data: 'Name' }, { data: 'Approved' }, { data: 'Denied' }, { data: 'tat_avg' } ], order: [[1, 'asc']], language: { emptyTable: "No data available" } }); table1.on('click', 'td.dt-control', function (e) { let tr = e.target.closest('tr'); let row = table1.row(tr); if (row.child.isShown()) { // This row is already open - close it row.child.hide(); tr.classList.remove('shown'); } else { // Open this row row.child(formatChild(row.data())).show(); tr.classList.add('shown'); var childTable = $(row.node()).next().find('.child-table'); // Handle click events for child rows childTable.on('click', 'td.dt-control', function () { var tr = $(this).closest('tr'); var childRow = childTable.DataTable().row(tr); console.log(childRow); console.log(childRow.data()); if (childRow.child.isShown()) { childRow.child.hide(); tr.classList.remove('shown'); } else { childRow.child(formatGrandChild(childRow.data())).show(); tr.classList.add('shown'); } }); } }); function formatChild(data) { var childTable = ''; // Check if the data has nested elements for (const key in data) { if (data.hasOwnProperty(key) && typeof data[key] === 'object') { const subArray = data[key]; childTable += '<table class="child-table" style="width:100%">' + '<tr class="child-row">' + '<td class="child-dt-control dt-control"></td>' + '<td class="child-dt-control">' + subArray.Name + '</td>' + '<td class="child-dt-control">' + subArray.Approved + '</td>' + '<td class="child-dt-control">' + subArray.Denied + '</td>' + '<td class="child-dt-control">' + subArray.tat_avg + '</td>' + '</tr>'; // If there are further nested elements, call formatGrandChild recursively childTable += formatGrandChild(subArray); } } return childTable; } function formatGrandChild(data) { var grandChildTable = ''; // Check if the data has nested elements for (const key in data) { if (data.hasOwnProperty(key) && typeof data[key] === 'object') { const subArray = data[key]; grandChildTable += '<table class="grandchild-table" style="width:100%">' + '<tr class="grandchild-row">' + '<td class="grandchild-dt-control dt-control"></td>' + '<td class="grandchild-dt">' + subArray.Name + '</td>' + '<td class="grandchild-dt">' + subArray.Approved + '</td>' + '<td class="grandchild-dt">' + subArray.Denied + '</td>' + '<td class="grandchild-dt">' + subArray.tat_avg + '</td>' + '</tr>' + '</table>'; } } return grandChildTable; } }, error: function (err) { console.log(err); }, });
问题原因及修复方案
核心问题
- 二级表格未初始化DataTable实例:原代码仅拼接了二级表格的HTML结构,但没有将其初始化为DataTable对象,导致调用
childTable.DataTable().row(tr)无法获取有效行数据,展开逻辑失效。 - 三级表格提前渲染:原代码在生成二级表格时直接渲染三级表格,不符合点击展开的交互逻辑。
修复后的完整代码
$.ajax({ url: "{{ path('api_path') }}", method: 'GET', dataType: 'json', data: {enterpriseID:{{user.enterpriseID}}, tab: 'pharmacy_analysis', start: startdate, end: enddate}, success: function (data) { pharmacy_analysis_data = example_data; // 销毁已存在的DataTable实例 if ($.fn.DataTable.isDataTable('#example1')) { $('#example1').DataTable().destroy(); } // 初始化一级表格 const parentTable = $('#example1').DataTable({ data: pharmacy_analysis_data, scrollY: 500, paging: false, columns: [ { data: null, className: 'dt-control', orderable: false, defaultContent: '', }, { data: 'Name' }, { data: 'Approved' }, { data: 'Denied' }, { data: 'tat_avg' } ], order: [[1, 'asc']], language: { emptyTable: "No data available" } }); // 一级表格行点击事件 parentTable.on('click', 'td.dt-control', function (e) { const tr = e.target.closest('tr'); const row = parentTable.row(tr); if (row.child.isShown()) { row.child.hide(); tr.classList.remove('shown'); } else { // 创建二级表格容器 row.child('<table class="child-table" style="width:100%"></table>').show(); tr.classList.add('shown'); // 提取二级表格数据 const childData = []; for (const key in row.data()) { if (typeof row.data()[key] === 'object' && row.data()[key].Name) { childData.push(row.data()[key]); } } // 初始化二级表格 const childTable = $(row.node()).next().find('.child-table').DataTable({ data: childData, paging: false, ordering: false, columns: [ { data: null, className: 'dt-control', orderable: false, defaultContent: '', }, { data: 'Name' }, { data: 'Approved' }, { data: 'Denied' }, { data: 'tat_avg' } ], language: { emptyTable: "No data available" } }); // 二级表格行点击事件 childTable.on('click', 'td.dt-control', function (e) { const tr = e.target.closest('tr'); const childRow = childTable.row(tr); if (childRow.child.isShown()) { childRow.child.hide(); tr.classList.remove('shown'); } else { // 创建三级表格容器 childRow.child('<table class="grandchild-table" style="width:100%"></table>').show(); tr.classList.add('shown'); // 提取三级表格数据 const grandChildData = []; for (const key in childRow.data()) { if (typeof childRow.data()[key] === 'object' && childRow.data()[key].Name) { grandChildData.push(childRow.data()[key]); } } // 初始化三级表格 $(childRow.node()).next().find('.grandchild-table').DataTable({ data: grandChildData, paging: false, ordering: false, columns: [ { data: 'Name' }, { data: 'Approved' }, { data: 'Denied' }, { data: 'tat_avg' } ], language: { emptyTable: "No data available" } }); } }); } }); }, error: function (err) { console.log(err); }, });
修复要点说明
- 分层初始化DataTable:一级、二级表格都单独初始化DataTable实例,确保行数据能被正确识别和操作。
- 按需渲染子表格:点击父行时才初始化对应子表格,点击子行时才初始化三级表格,避免提前加载冗余内容。
- 规范数据提取:遍历父数据时,仅收集包含
Name属性的对象作为子表格数据源,过滤无效数据。 - 实例化绑定事件:每个表格实例单独绑定点击事件,避免事件冒泡或目标混淆。
内容的提问来源于stack exchange,提问作者Akshay
相关产品推荐
相关产品推荐

