You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在DataTables执行搜索等操作后保留本地修改内容?

解决DataTables服务端模式下本地修改丢失的问题

看起来你遇到了DataTables服务端模式的典型问题:每次交互(搜索、分页、切换显示条数)都会重新拉取服务器原始数据,覆盖你本地修改的内容。针对DataTables 1.9.4版本,我们可以通过记录并恢复本地修改的方式解决这个问题,具体方案如下:

核心思路

因为服务端模式下DataTables会完全替换表格数据,我们需要:

  1. 用一个对象存储用户的所有本地修改,以行的唯一ID作为键(避免分页/搜索后行索引变化导致记录错乱)。
  2. 在表格每次重绘后,自动将保存的修改重新应用到对应单元格。

修改后的完整代码

$(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" }
        ]
    });
});

关键细节说明

  1. 行唯一ID:一定要用每行的唯一标识(比如数据库ID)来关联修改记录,不能用行索引——因为分页、搜索后行索引会变化,会导致记录错乱。你需要根据自己的返回数据调整rowUniqueId的获取方式。
  2. 事件绑定:因为表格每次重绘都会重新生成DOM元素,所以必须在fnDrawCallback里重新绑定修改事件,并且用off('change')避免重复绑定。
  3. fnUpdate参数:最后两个参数设为false,表示不触发表格重绘和服务端请求,避免不必要的性能开销和数据覆盖。

额外提示

如果你需要将本地修改永久保存到服务器,可以在用户完成修改后,遍历cellModifications对象,收集所有修改数据,一次性提交到后端接口。

内容的提问来源于stack exchange,提问作者JohanL11

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 09:22:50