Bootstrap 5响应式DataTable展开行后删除/编辑按钮失效求助
响应式DataTable移动端展开行后编辑/删除按钮失效问题
- 基于Bootstrap 5搭建的响应式DataTable,在桌面端未展开行状态下,编辑、删除按钮均可正常触发;
- 切换到移动端屏幕,点击
+展开行后,按钮完全无法触发点击事件; - 非专业开发者,通过Google Script制作页面,需解决该问题。
问题代码
/* Prevent forms from submitting. */ function preventFormSubmit() { var forms = document.querySelectorAll('form'); for (var i = 0; i < forms.length; i++) { forms[i].addEventListener('submit', function(event) { event.preventDefault(); }); } } window.addEventListener("load", functionInit, true); /** * INITIALIZE FUNCTIONS ONLOAD * */ function functionInit(){ preventFormSubmit(); getLastTenRows(); }; /** * HANDLE FORM SUBMISSION * */ function handleFormSubmit(formObject) { google.script.run.withSuccessHandler(createTable).processForm(formObject); document.getElementById("message").innerHTML = "<div class='alert alert-warning' role='alert'>Added the record successfully.</div>"; document.getElementById("myForm").reset(); } /** * Clear form when pop-up is closed. * */ function clearForm() { document.getElementById("message").innerHTML = ""; document.getElementById("myForm").reset(); } google.script.run.withSuccessHandler(createTable).getAllData(); document.getElementById('resp-spinner5').classList.remove("d-none"); document.getElementById('resp-spinner6').classList.remove("d-none"); document.getElementById('resp-spinner7').classList.remove("d-none"); document.getElementById('resp-spinner8').classList.remove("d-none"); document.getElementById('resp-spinner9').classList.remove("d-none"); document.getElementById('resp-spinner10').classList.remove("d-none"); function createTable(dataArray) { $('#btn-close').click() $(document).ready(function(){ document.getElementById('resp-spinner5').classList.add("d-none"); document.getElementById('resp-spinner6').classList.add("d-none"); document.getElementById('resp-spinner7').classList.add("d-none"); document.getElementById('resp-spinner8').classList.add("d-none"); document.getElementById('resp-spinner9').classList.add("d-none"); document.getElementById('resp-spinner10').classList.add("d-none"); $('#dataTable').DataTable({ data: dataArray.slice(1), columns: [ { title: "ID" }, { title: "Name" }, { title: "State" }, { title: "Date" }, { title: "Mobile No" }, { title: "Address" }, { title: "Remarks" }, { title: "Edit", "render": function (data,type, row, meta){ return "<button type='button' class='btn btn-outline-warning btn-xs editBtn' data-toggle='modal' data-target='#myModal' onclick='editData(this);'><i class='fa fa-edit'></i></button>"; } }, { title: "Delete", "render": function (data,type){ return "<button type='button' class='btn btn-outline-danger btn-xs deleteBtn' onclick='deleteData(this);'><i class='fa fa-trash''></i></button>"; } }, ], "fnRowCallback": function(nRow, aData, iDisplayIndex) { nRow.setAttribute('id',aData[0]); }, destroy:true, responsive:true, lengthMenu: [ [5, 10, 25, 50, 100, -1 ], ['5', '10', '25', '50','100', 'All' ] ], order: [[2, "asc"], [2, "asc"]], }); }); } /** * DELETE DATA * */ function deleteData(el) { Swal.fire({ position:'top', title: 'Are you sure?', text: "You won't be able to revert this!", icon: 'warning', showCancelButton: true, confirmButtonColor: '#3085d6', cancelButtonColor: '#d33', cancelButtonText: 'Cencel', confirmButtonText: 'Ok' }).then((result) => { if (result.isConfirmed) { Swal.fire('Deleted!','Your file has been deleted.') } if (result.isDismissed) { swal.fire("Cancelled!", "Files not deleted!", "warning"); console.log("Doing Nothing") var recordId = el.parentNode.parentNode.cells[0].innerHTML; google.script.run.withSuccessHandler(createTable).deleteData(recordId); } }); } /** * EDIT DATA * */ function editData(el){ var recordId = el.parentNode.parentNode.cells[0].innerHTML; google.script.run.withSuccessHandler(populateForm).getRecordById(recordId); } /** * POPULATE FORM * */ function populateForm(records){ document.getElementById('RecId').value = records[0][0]; document.getElementById('name').value = records[0][1]; document.getElementById('State').value = records[0][2]; document.getElementById('date').value = records[0][3]; document.getElementById('data1').value = records[0][4]; document.getElementById('data2').value = records[0][5]; document.getElementById('data3').value = records[0][6]; document.getElementById("message").innerHTML = "<div class='alert alert-warning' role='alert'>Update Record [ID: "+records[0][0]+"]</div>"; } /** * RETRIVE DATA FROM GOOGLE SHEET FOR State DROPDOWN * */ function createStateDropdown() { google.script.run.withSuccessHandler(StateDropDown).getDropdownList("State!A1:A4"); } /** * POPULATE State DROPDOWNS * */ function StateDropDown(values) { var list = document.getElementById('State'); for (var i = 0; i < values.length; i++) { var option = document.createElement("option"); option.value = values[i]; option.text = values[i]; list.appendChild(option); } } function loading(){ window.addEventListener("load", functionInit, false); window.addEventListener("load", preventFormSubmitSearch, true); }
解决方案
1. 核心问题分析
DataTable响应式展开的行是动态生成的DOM元素,原代码用onclick绑定事件仅对初始渲染的DOM生效;同时展开行后DOM层级改变,el.parentNode.parentNode.cells[0]无法正确获取ID。
2. 具体修改步骤
步骤1:修改按钮渲染逻辑,移除onclick,添加数据ID
在createTable的列配置中,给按钮添加data-id存储行ID,去掉onclick:
// Edit列修改 { title: "Edit", "render": function (data,type, row, meta){ return "<button type='button' class='btn btn-outline-warning btn-xs editBtn' data-toggle='modal' data-target='#myModal' data-id='"+row[0]+"'><i class='fa fa-edit'></i></button>"; } }, // Delete列修改 { title: "Delete", "render": function (data,type, row){ return "<button type='button' class='btn btn-outline-danger btn-xs deleteBtn' data-id='"+row[0]+"'><i class='fa fa-trash'></i></button>"; } },
步骤2:用事件委托绑定动态元素的点击事件
在createTable函数中,DataTable初始化完成后添加事件委托(替换原editData和deleteData函数):
function createTable(dataArray) { $('#btn-close').click() $(document).ready(function(){ // ... 原隐藏spinner代码不变 ... $('#dataTable').DataTable({/* ... 原配置不变 ... */}); // 编辑按钮事件委托 $('#dataTable').on('click', '.editBtn', function(){ var recordId = $(this).data('id'); google.script.run.withSuccessHandler(populateForm).getRecordById(recordId); }); // 删除按钮事件委托 $('#dataTable').on('click', '.deleteBtn', function(){ var recordId = $(this).data('id'); Swal.fire({ position:'top', title: 'Are you sure?', text: "You won't be able to revert this!", icon: 'warning', showCancelButton: true, confirmButtonColor: '#3085d6', cancelButtonColor: '#d33', cancelButtonText: 'Cancel', confirmButtonText: 'Ok' }).then((result) => { if (result.isConfirmed) { Swal.fire('Deleted!', 'Your file has been deleted.', 'success'); google.script.run.withSuccessHandler(createTable).deleteData(recordId); } else if (result.isDismissed) { Swal.fire("Cancelled!", "Files not deleted!", "warning"); } }); }); }); }
注:修复了原删除函数中,删除请求写在取消分支的逻辑错误
步骤3:修复脚本加载顺序和冗余代码
- 将jQuery脚本放在所有自定义代码最前面:
<script src="~/lib/jquery/dist/jquery.js"></script> <!-- 其他依赖(DataTable、Bootstrap、SweetAlert等)也需放在自定义脚本前 --> <script>/* 自定义JS代码 */</script> - 删除冗余的重复初始化代码:
// 删掉这段无效代码 $('#datatable').DataTable().columns.adjust().responsive.recalc();
内容的提问来源于stack exchange,提问作者Yurii Holovko
相关产品推荐
相关产品推荐

