Search code examples
javascriptjqueryjqgridfree-jqgrid

jqgrid - inline editing, post only changed data


I have a jqGrid where I would like to check for cell data and only post the columns of which the data has changed.

Consider this is my colModel

colModel: [{
    name: 'I_PK',
    index: 'u.I_PK',
    align: 'right',
    editable: false,
    sopt: ['cn', 'eq', 'ne', 'lt', 'le', 'gt', 'ge', 'bw', 'ew', 'nc']
}, {
    name: 'W3LabelSelected',
    index: 'u.W3LabelSelected',
    align: 'center',
    width: 170,
    editable: false,
    edittype: 'checkbox',
    formatter: "checkbox",
    search: false,
    formatoptions: {
        disabled: false
    },
    editoptions: {
        value: "1:0"
    }
}, {
    name: 'I_ItemNumID',
    index: 'u.I_ItemNumID',
    align: 'right',
    editable: true,
    editoptions: {
        dataEvents: [{
            type: 'focusin',
            fn: function (e) {
                var elem = e.target;
                setTimeout(function () {
                    elem.select();
                }, 50);
            }
        }]
    }
}, {
    name: 'Quantity',
    index: 'u.Quantity',
    align: 'right',
    editable: true,
    editoptions: {
        dataEvents: [{
            type: 'focusin',
            fn: function (e) {
                var elem = e.target;
                setTimeout(function () {
                    elem.select();
                }, 50);
            }
        }]
    }
}],

In this grid, two of my columns are editable. Now let's say if I make changes in one of the columns of any row in inline editing, then only that cell's value should be posted. Current functionality posts all the cells of that specific row. Is this possible?

I found some questions here and there about this but none seem to be addressing this specific problem.

Basically the idea I can think of is that before saving, if I can somehow compare the original data of all the editable cells of that row to the new value before getting posted, I can eliminate the cells of which the data has not changed and only post the cell which has changed.

Sample grid: http://jsfiddle.net/dipenshah8/HJema/203/


Solution

  • I would suggest you to use serializeSaveData callback of inline editing or serializeRowData callback of old versions of jqGrid. The callback allows you to customize the data, which will be send to the server. The modified demo http://jsfiddle.net/OlegKi/HJema/206/ uses the following options:

    inlineEditing: {
        keys: true,
        serializeSaveData: function (postData) {
            var changedData = {}, prop, p = $(this).jqGrid("getGridParam"),
                idname = p.keyName || p.prmNames.id;
    
            for (prop in postData) {
                if (postData.hasOwnProperty(prop) &&
                    (postData[prop] !== p.savedRow[0][prop] || prop === idname)) {
                    changedData[prop] = postData[prop];
                }
            }
            alert(JSON.stringify(changedData));
            return changedData;
        }
    }
    

    The code of serializeSaveData callback enumerate all properties which will be send to the server by default and generate new object changedData instead of postData. The code compare the value of all properties of postData with the corresponding values of savedRow[0] parameter, which contains the row before starting editing.

    UPDATED: The above code should be a little complexer if the data could have formatter: "date". jqGrid saves formatted value in savedRow[0]. One can modify the above code to the following:

    inlineEditing: {
        keys: true,
        serializeSaveData: function (postData) {
            var changedData = {}, prop, p = $(this).jqGrid("getGridParam"),
                idname = p.keyName || p.prmNames.id,
                oldValue, cm, formatoptions;
    
            for (prop in postData) {
                oldValue = p.savedRow[0][prop];
                if (p.iColByName[prop] != null) {
                    cm = p.colModel[p.iColByName[prop]];
                    formatoptions = cm.formatoptions || {};
                    if (cm.formatter === "date" && formatoptions.sendFormatted !== true) {
                        oldValue = $.unformat.date.call(this, oldValue, cm);
                    }
                }
                if (postData.hasOwnProperty(prop) &&
                        (postData[prop] !== oldValue || prop === idname)) {
                    changedData[prop] = postData[prop];
                }
            }
            alert(JSON.stringify(changedData));
            return changedData;
        }
    }
    

    See the modified demo http://jsfiddle.net/OlegKi/HJema/209/