如何在DataTables执行搜索等操作后保留本地修改内容?
解决DataTables服务端模式下本地修改丢失的问题
看起来你遇到了DataTables服务端模式的典型问题:每次交互(搜索、分页、切换显示条数)都会重新拉取服务器原始数据,覆盖你本地修改的内容。针对DataTables 1.9.4版本,我们可以通过记录并恢复本地修改的方式解决这个问题,具体方案如下:
核心思路
因为服务端模式下DataTables会完全替换表格数据,我们需要:
- 用一个对象存储用户的所有本地修改,以行的唯一ID作为键(避免分页/搜索后行索引变化导致记录错乱)。
- 在表格每次重绘后,自动将保存的修改重新应用到对应单元格。
修改后的完整代码
$(document).ready(function(){ var listeRespPosePlv = $('#listeRespPosePlv').val(); listeRespPosePlv = JSON.parse(listeRespPosePlv); var listeRespPoseFormatted = []; $(listeRespPosePlv).each(function(i, v){ listeRespPoseFormatted.push({'value': v.id_responsable_pose_plv, 'label': v.libelle}); }); // 存储本地修改记录:键=行唯一ID,值={列索引: 修改后的值} var cellModifications = {}; $('#attribution_pose')[0].currentDataTable = $('#attribution_pose').dataTable({ "bProcessing": true, "bServerSide": true, "bStateSave": true, 'sAjaxSource': Router.url('campagne-plv-attribution'), 'aLengthMenu': [ [10, 25, 50, 1000, -1], [10, 25, 50, 1000, "All"] ], 'iDisplayLength': 1000, 'fnServerParams' : function( aoData ) { var idCampagnePlv = $('#id_campagne_plv').val(); aoData.push( { 'name': 'id_campagne_plv', 'value': idCampagnePlv } ); }, 'fnDrawCallback': function(oSettings){ $('.datepicker').datepicker(); var tableInstance = oSettings.oInstance; // 1. 绑定可编辑控件的修改事件,记录修改内容 $('#attribution_pose tbody tr').each(function(rowIndex) { var rowData = tableInstance.fnGetData(rowIndex); // 👉 这里要根据你的数据结构调整:假设第1列(索引0)是行的唯一ID var rowUniqueId = rowData[0]; // 先解绑旧事件,避免重复触发 $(this).find('select, input').off('change').on('change', function() { var colIndex = $(this).closest('td').index(); var newValue = $(this).val(); // 保存修改到记录对象 if (!cellModifications[rowUniqueId]) { cellModifications[rowUniqueId] = {}; } cellModifications[rowUniqueId][colIndex] = newValue; // 更新DataTables本地数据(不触发重绘和服务端请求) tableInstance.fnUpdate(newValue, rowIndex, colIndex, false, false); }); }); // 2. 恢复之前的本地修改 $('#attribution_pose tbody tr').each(function(rowIndex) { var rowData = tableInstance.fnGetData(rowIndex); var rowUniqueId = rowData[0]; if (cellModifications[rowUniqueId]) { $.each(cellModifications[rowUniqueId], function(colIndex, newValue) { // 同步更新表格数据和DOM控件的值 tableInstance.fnUpdate(newValue, rowIndex, colIndex, false, false); $(this).find('td').eq(colIndex).find('select, input').val(newValue); }.bind(this)); } }); // 你的原有测试代码(可保留或删除) var table = this.fnGetData(); var test = $('#attribution_pose tbody tr'); for(var i = 0; i < table.length; i++){ for(var j = 0; j < table[i].length; j++){ if(table[i][j].localeCompare(test[i].cells[j].children[0].outerHTML) !== 0){ console.log('Diff'); }else{ console.log('Ok'); } } } }, 'oLanguage': { 'sUrl': Constante.get('base_full_url')+'assets/vendor/datatables/french.json' } }).columnFilter({ sPlaceHolder: "head:before", aoColumns: [ { type: "text" }, { type: "text" }, { type: "text" }, { type: "text" }, { type: "select" , values: listeRespPoseFormatted}, { type: "text" }, { type: "text" }, { type: "text" }, null, null, null, null, { type: "text" } ] }); });
关键细节说明
- 行唯一ID:一定要用每行的唯一标识(比如数据库ID)来关联修改记录,不能用行索引——因为分页、搜索后行索引会变化,会导致记录错乱。你需要根据自己的返回数据调整
rowUniqueId的获取方式。 - 事件绑定:因为表格每次重绘都会重新生成DOM元素,所以必须在
fnDrawCallback里重新绑定修改事件,并且用off('change')避免重复绑定。 fnUpdate参数:最后两个参数设为false,表示不触发表格重绘和服务端请求,避免不必要的性能开销和数据覆盖。
额外提示
如果你需要将本地修改永久保存到服务器,可以在用户完成修改后,遍历cellModifications对象,收集所有修改数据,一次性提交到后端接口。
内容的提问来源于stack exchange,提问作者JohanL11
相关产品推荐
相关产品推荐

