3

Scenario of what I'm trying to achieve:

  • I retrieve some data from the server
  • I loop the data and add/alter values for some fields
  • The data is being displayed in a grid
  • The user locally edits the data
  • When finished, the user submits the entire grid data to the server

How I tried to achieve it:

I made a jqGrid with loadonce:true, editurl:'clientArray' and inline editing. In loadComplete I loop through the data received from the server and add some values. An external button is used to get the grid data using .jqGrid('getGridParam','data') and send it to the server.

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

Problem: The loadComplete event fires when the user changes the grid page or does a search. Which results in overriding any data edited by the him. I tried using the beforeProcessing event instead but it never fires (Edit: It didn't work when testing with local data, but works with loadonce). I could not find any other suitable event in the documentation.

I reproduced the scenario in this demo.

Question: How should I correctly modify the data after receiving it from the server and let the user edit locally, without overriding his edits when he changes the page or does a search?

Note: I am using free-jqGrid 4.14

Alexandru Severin
  • 6,021
  • 11
  • 48
  • 71

1 Answers1

3

One should use beforeProcessing instead of loadComplete to make some modification in the data loaded from the server. The callback is very practical in loadonce: true scenario because it will be called only once after loading the data from the server.

It's very important to understand that one should try to reduce the number of changes on DOM of HTML page. If you change the data before processing by HTML parser then it works very quickly: you change one property and only the property will be changed. On the other side, changing one element on HTML page follows recalculation and probably the changes of all other elements existing on the page. For example you insert an element over the grid. Then the position of the grid (and thus all other elements of the grid) will be changes. At least web browser have to verify whether some changes of all existing elements required. It's browser reflow. It you makes changes of HTML element in the loop (like the call of setRowData inside of loadComplete) then it essentially reduce the speed of the HTML page.

One more remark. I'd recommend you to use Echo service of JSFiddle (see here) to simulate loading of data from the server. The corresponding code could be the following:

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>');
}

See modified demo 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 of code)

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

as the result the data used in the first column will be converted to number instead of holding the data as strings.

Oleg
  • 220,925
  • 34
  • 403
  • 798