如何在 jqGrid 处理之前更改从服务器接收的数据

How to alter data received from the server before processing by jqGrid

我想要实现的场景:

我是如何实现的:

我用 loadonce:trueediturl:'clientArray' 和内联编辑制作了一个 jqGrid。在 loadComplete 中,我遍历从服务器接收到的数据并添加一些值。外部按钮用于使用 .jqGrid('getGridParam','data') 获取网格数据并将其发送到服务器。

loadComplete: function(data){
    for(var i=0; i<data.rows.length; i++){
      var row = data.rows[i];
      grid.jqGrid('setRowData', row.id, {
        missingData: 'someDefaultValue'
      });
    }
}

问题: loadComplete 事件在用户更改网格页面或进行搜索时触发。这导致覆盖他编辑的任何数据。我尝试改用 beforeProcessing 事件,但它从未触发 (编辑:使用本地数据测试时它不起作用,但适用于 loadonce)。我在 documentation.

中找不到任何其他合适的事件

我在 this 演示中重现了场景。

问题:我应该如何在从服务器接收到数据后正确修改并让用户在本地编辑,而不会在他更改页面或进行搜索时覆盖他的编辑?

注:我使用的是free-jqGrid 4.14

应该使用 beforeProcessing 而不是 loadComplete 来对从服务器加载的数据进行一些修改。该回调在loadonce: true场景下非常实用,因为它只会在从服务器加载数据后调用一次。

了解 HTML 页面 的 DOM 上 的更改数量非常重要。如果您在 HTML 解析器处理之前更改数据,那么它工作得非常快:您更改一个 属性 并且只有 属性 会被更改。另一方面,更改 HTML 页面上的一个元素后会重新计算,并且可能会更改页面上存在的 所有 其他元素。例如,您在网格上插入一个元素。然后网格的位置(以及网格的所有其他元素)将发生变化。至少 Web 浏览器必须验证是否需要对 all 现有元素进行一些更改。是 browser reflow。如果您在循环中更改 HTML 元素(就像在 loadComplete 中调用 setRowData),那么它实际上会降低 HTML 页面的速度。

再多说一句。我建议您使用 JSFiddle 的 Echo 服务(参见 here)来模拟从服务器加载数据。对应的代码可能是:

var i, data = [], grid = $('#grid');

for(i=0; i<4; i++) {
    data.push({id:i, select1: i%3});
}

grid.jqGrid({
    datatype: "json",
    mtype: "POST",
    url: "/echo/json/",
    postData: {
        json: JSON.stringify(data)
    },
    loadonce: true,
    forceClientSorting: true,
    caption: 'Testing',
    editurl: 'clientArray',
    rowNum: 2,
    rowList: [2, 4],
    pager: true,
    colModel: [
        {name:'select1', label: 'Server status', editable:true, edittype:'select', formatter:'select', template: "integer", editoptions:{
            value:'0:AAA;1:BBB;2:CCC'
        }},
        {name:'select2', label: 'Local status', editable: true, edittype: 'select', formatter:'select', editoptions:{
            value:'0:AAA;1:BBB;2:CCC'
        }},
        {name:'act', template:'actions'}
    ],
    inlineEditing: {
        keys: true
    },
    beforeProcessing: function(data){
        var i;
        for(i=0; i<data.length; i++){
            data[i].select2 = 0;
        }
    }
});

$('#b1').click(function(){
    $('#out').empty()
    var i, gridData = grid.jqGrid('getGridParam','data');
    for(i=0; i<gridData.length; i++){
       out(JSON.stringify(gridData[i]));
    }
});

function out(message){
    $('#out').append('<p>' + message +'</p>');
}

查看修改后的演示 https://jsfiddle.net/OlegKi/c09fnaca/8/. I added template: "integer" in the first column only to demonstrate conversion of data to numbers. Free jqGrid supports convertOnSave callback (see the wiki article), which helps to make some kind of conversions during saving the local data. for example defines the following callback (see the lines 代码)

convertOnSave: function (options) {
    var nData = options.newValue;
    return isNaN(nData) ? nData : parseInt(nData, 10);
}

因此,第一列中使用的数据将被转换为数字,而不是将数据保存为字符串。