Search code examples
jqgridform-editing

jqGrid: Form edits saved to row but all changes lost when paging back or forth


I am using form editing for local data. I am able to edit the values in the form and set the values back to the row (using setRowData). But when I page back or forth, the changes are lost.

How do I save the changes to the row and the underlying source in the grid? Later I have to iterate the rows, validate all the errors are corrected (using the edit form), and post it to server.

Code:

var gridId = 'mygrid';
var pagerId = 'mygridpager';

var grid = $('#mygrid');
var pager = $('#mygridpager');

grid.jqGrid({
    caption: caption,
    colModel: getColModel(),
    recreateForm: true,

    hidegrid: true,
    sortorder: 'desc',
    viewrecords: true,
    multiselect: true,
    rownumbers: true,

    autowidth: true,
    height: '100%',
    scrollOffset: 0,

    datatype: 'local',
    data: dataAsArray,
    localReader: {
        repeatitems: true,
        cell: '',
        id: 2
    },

    pager: '#' + pagerId,
    pgbuttons: true,
    rowNum: 5,
    rowList: [2, 5, 7, 10, 250, 500]
});

grid.jqGrid('navGrid',
    '#' + pagerId,
    {
        add: false,
        del: false,
        search: false,

        edit: true,
        edittext: 'Fix Error',
        editicon: 'ui-icon-tag',
        editurl: 'clientArray',

        refreshtext: 'Refresh',
        recreateForm: true
    },
    {
        // edit options
        editCaption: 'Fix Error',
        editurl: 'clientArray',
        recreateForm: true,
        beforeShowForm: function(form) {
            /* Custom style for elements. make it disabled etc */
        },
        onclickSubmit: function(options, postdata) {
                    var idName= $(this).jqGrid('getGridParam').prmNames.id;

                    // [UPDATED]
                    if (postdata[idName] === undefined) {
                        var idInPostdata = this.id + "_id";
                        postdata[idName] = postdata[idInPostdata];
                        postdata['row'] = postdata[idInPostdata];
                    }

            $('#mygrid').jqGrid('setRowData', postdata.row, postdata);

            if (options.closeAfterEdit) {
                $.jgrid.hideModal('#editmod' + gridId, {
                    gb: '#gbox_' + gridId,
                    jqm: options.jqModal,
                    onClose: options.onClose
                });
            }

            options.processing = true;

            return {};
        }
    },
    {}, // add options
    {}, // del options
    {} //search options
).trigger('reloadGrid');

Your help is appreciated.

Thanks


Solution

  • I suppose that the reason of your problem is usage of array format (repeatitems: true in localReader) of input data. I suppose that you need build array from postdata and use it as the parameter of setRowData instead of postdata.

    If the advice will don't help you that you should post more full code of the grid with the test data. The code like colModel: getColModel(), don't really help. In other words you should post enough information to reproduce the problem. The best would be a working demo in http://jsfiddle.net/. If you prepare such demo please use jquery.jqGrid.src.js instead of jquery.jqGrid.min.js.

    UPDATED: The problem in your code is the usage arrays is items if input data (you use repeatitems: true in localReader). The current implementation of setRowData don't support (works incorrect) in the case. For example if you have such data initially

    enter image description here

    and start editing of the third row you will have something like the following

    enter image description here

    after usage the like $('#mygrid').jqGrid('setRowData', postdata.row, postdata); inside of onclickSubmit. So the internal data will be incorrectly modified.

    To fix the problem I suggest overwrite the current implementation of setRowData by including the following code

    $.jgrid.extend({
        setRowData : function(rowid, data, cssp) {
            var nm, success=true, title;
            this.each(function(){
                if(!this.grid) {return false;}
                var t = this, vl, ind, cp = typeof cssp, lcdata=t.p.datatype === "local" && t.p.localReader.repeatitems === true? [] : {}, iLocal=0;
                ind = $(this).jqGrid('getGridRowById', rowid);
                if(!ind) { return false; }
                if( data ) {
                    try {
                        $(this.p.colModel).each(function(i){
                            nm = this.name;
                            var dval =$.jgrid.getAccessor(data,nm);
                            if( dval !== undefined) {
                                vl = this.formatter && typeof this.formatter === 'string' && this.formatter === 'date' ? $.unformat.date.call(t,dval,this) : dval;
                                if (t.p.datatype === "local" && t.p.localReader.repeatitems === true) {
                                    lcdata[iLocal] = vl;
                                } else {
                                    lcdata[nm] = vl;
                                }
                                vl = t.formatter( rowid, dval, i, data, 'edit');
                                title = this.title ? {"title":$.jgrid.stripHtml(vl)} : {};
                                if(t.p.treeGrid===true && nm === t.p.ExpandColumn) {
                                    $("td[role='gridcell']:eq("+i+") > span:first",ind).html(vl).attr(title);
                                } else {
                                    $("td[role='gridcell']:eq("+i+")",ind).html(vl).attr(title);
                                }
                            }
                            if (nm !== "cb" && nm !== "subgrid" && nm !== "rn") {
                                iLocal++;
                            }
                        });
                        if(t.p.datatype === 'local') {
                            var id = $.jgrid.stripPref(t.p.idPrefix, rowid),
                            pos = t.p._index[id], key;
                            if(t.p.treeGrid) {
                                for(key in t.p.treeReader){
                                    if(t.p.treeReader.hasOwnProperty(key)) {
                                        delete lcdata[t.p.treeReader[key]];
                                    }
                                }
                            }
                            if(pos !== undefined) {
                                t.p.data[pos] = $.extend(true, t.p.data[pos], lcdata);
                            }
                            lcdata = null;
                        }
                    } catch (e) {
                        success = false;
                    }
                }
                if(success) {
                    if(cp === 'string') {$(ind).addClass(cssp);} else if(cssp !== null && cp === 'object') {$(ind).css(cssp);}
                    $(t).triggerHandler("jqGridAfterGridComplete");
                }
            });
            return success;
        }
    });
    

    I will post my suggestion later to trirand. So one can hopes that the problem will be fixed in the next version of jqGrid.