Toolbar search local data, retain value in cell ev

2019-05-31 08:00发布

问题:

I am using toolbar searching on local data(because I am using optionloadonce: true). In my grid, there is one column 'Transfer Qty.' which is by default editable.

I want a functionality like, suppose I entered some value in column 'Transfer Qty.' in 4th row whose Lot No. name is 'OpStk_Leher_Mumbai-500' (for that please refer above image) and if I make search with search-string 'P-35' and press enter, it gives me first three row as a search result as per my search string and it will exclude 4th row in which I entered a value. To get an idea please refer following image...

But if I remove search string from search box and press enter, it gives me all records but, the value I entered in 4th row in column 'TransferQty' gets disappeared and I want to retain that value anyhow.

If anyone knows how to do this, kindly share your valuable ideas.

To get understanding as per technical perspective, my jQgrid code is as follows:

 var oGrid = $('#tbLots'), 
 topPagerSelector = '#' + $.jgrid.jqID(oGrid[0].id) + "_toppager", lastSel;

oGrid.jqGrid({
    url: sRelativePath + '/WSAjax.asmx/GetDataForGrid',
    mtype: "POST",
    datatype: "json",
    ajaxGridOptions: { contentType: "application/json; charset=utf-8" },
    serializeGridData: function (data) {
        return JSON.stringify(data);
    },
    jsonReader: {
        root: "d.rows",
        page: "d.page",
        total: "d.total",
        records: "d.records"
    },
    colNames: ['SISDIdForExch', 'SubLotId', 'Lot#', 'Expiry Date', 'Qty.', 'Transfer Qty.'],
    colModel: [
        { name: 'SISDIdForExch', index: 'SISDIdForExch', hidden: true },
        { name: 'SubLotId', index: 'SubLotId', hidden: true },
        { name: 'LotNo', index: 'LotNo', editable: false, sortable: false, width: 100},
        {name: 'Expiry', index: 'Expiry', editable: false, search: false, align: 'center', formatter: 'date', formatoptions: { srcformat: 'm/d/Y', newformat: 'd/m/Y' }, sortable: false, width: 60 },
        { name: 'BucketQty', index: 'BucketQty', editable: false, search: false, template: viewNumTemplate, width: 60 },
        { name: 'TransferQty', index: 'TransferQty', editable: true, search: false, template: editNumTemplate, width: 60, editrules: { minValue: 0.00 },
            editoptions: {
                dataInit: function (domElem) {
                    $(domElem).on("blur", function () {
                        calculateTotalTransferQty($("#tbLots"));
                    });
                }
            }
        }
    ],
    prmNames: { page: "pageIndex", rows: "pageSize", sort: "sortIndex", order: "sortDirection", search: "_search" },
    search: false,
    postData: {
        filters: null,
        spName: 'GetLotDetails',
        paramXML: $xmlDoc.html().toString()
    },
    width: 'auto',
    height: 'auto',
    rowNum: 1000,
    sortname: '',
    sortorder: 'asc',
    page: 1,
    gridview: true,
    toppager: true,
    autoencode: true,
    ignoreCase: true,
    viewrecords: true,
    caption: 'Item Lots',
    editurl: 'clientArray',
    footerrow: true,
    loadonce: true,
    gridComplete: function () {
        $("table#tbLots tr:last").addClass('ireg-jqgrid-lastrow');
        $("tr.footrow td").addClass('ireg-jqgrid-lastrow').addClass('ireg-jqgrid-footer');
    },
    loadComplete: function (data) {
        updateJqGridButtonState($(this), jqGridMode.None);
        //Following piece of code made 'Transfer Qty.' column by default editable. 
        var l_oIds = oGrid.jqGrid('getDataIDs'), i;
        for (i = 0; i < l_oIds.length; i++) {
            oGrid.jqGrid('editRow', l_oIds[i], true);
        }
        //Set focus on first editable cell. 
        if (l_oIds.length > 0)
            $('#' + l_oIds[0] + '_TransferQty').get(0).focus();
    },
    onSelectRow: function (rowid) {
        if (rowid && rowid != lastSel) {
            if (typeof lastSel !== "undefined") {
                $(this).jqGrid('restoreRow', lastSel);
            }
            lastSel = rowid;
        }
        updateJqGridButtonState($(this), jqGridMode.None);
    }
});
oGrid.jqGrid('filterToolbar', { stringResult: true, defaultSearch: 'cn', //groupOp: 'OR',
    beforeSearch: function () {
        if (colDataTypes.length != 0 && colDataTypes != undefined) {
            var oRules = new Array();
            var postdata = $('#tbLots').jqGrid('getGridParam', 'postData'), 
            oCustFilter = $.parseJSON(postdata.filters), colName, searchStr, operator, groupOperator = '';
            for (var i = 0; i < oCustFilter.rules.length; i++) {
                groupOperator = oCustFilter.groupOp;
                searchStr = oCustFilter.rules[i].data;
                colName = oCustFilter.rules[i].field;
                operator = oCustFilter.rules[i].op;
                oRules.push({ field: colName, op: operator, data: searchStr });
            }

            if (searchVal != null && searchVal != '') {
                var oFilter = { groupOp: groupOperator, rules: oRules };
                $.extend(postdata, { filters: JSON.stringify(oFilter) });
                $('#tbLots').jqGrid('setGridParam', { search: true, postData: postdata });
                $('#tbLots').trigger("reloadGrid", [{ page: 1}]);
            }
        }
        return true;
    }
});
//Added afterRefresh function to clear toolbar.
oGrid.jqGrid('navGrid', topPagerSelector, { add: false, edit: false, del: false, search: false,
    afterRefresh: function () {
        $(this)[0].clearToolbar();
    } 
 }, {}, {}, {}, {});

Here is my updated code, the way you taught me to do

oGrid.jqGrid('filterToolbar', { stringResult: true, defaultSearch: 'cn', //groupOp: 'OR',
    beforeSearch: function () {
       if (colDataTypes.length != 0 && colDataTypes != undefined) {
            var oRules = new Array();
            var postdata = $('#tbLots').jqGrid('getGridParam', 'postData'), 
                oCustFilter = $.parseJSON(postdata.filters), colName, searchStr, operator, groupOperator = '';
            for (var i = 0; i < oCustFilter.rules.length; i++) {
                groupOperator = oCustFilter.groupOp;
                searchStr = oCustFilter.rules[i].data;
                colName = oCustFilter.rules[i].field;
                operator = oCustFilter.rules[i].op;
                //iReg-1821: Uncommneted the following code.
                var colIndex = getColumnIndexByName($('#tbLots'), colName);
                var searchVal = '', bAttachQuote = false;

                if ('STRING' === colDataTypes[colIndex]) {
                    searchVal = searchStr;
                    bAttachQuote = true;
                } 

                oRules.push({ field: colName, op: operator, data: searchStr, coldatatype: colDataTypes[colIndex], attachquote: bAttachQuote });
            }

            if (searchVal != null && searchVal != '') {
                var oFilter = { groupOp: groupOperator, rules: oRules };
                $.extend(postdata, { filters: JSON.stringify(oFilter) });
                $('#tbLots').jqGrid('setGridParam', { search: true, postData: postdata });
                $('#tbLots').trigger("reloadGrid", [{ page: 1}]);
            }
        }

        HERE IS MY CODE, WHAT YOU TAUGHT ME TO DO 
        var l_oIds = oGrid.jqGrid('getDataIDs'), i;
        for (i = 0; i < l_oIds.length; i++) {
            oGrid.jqGrid('saveRow', l_oIds[i], false, 'clientArray');
        }

        return true;
    }
});

回答1:

The origin of the problem seems to me in the using the behavior which you described like

... one column 'Transfer Qty.' which is by default editable.

You calls editRow for all rows of the grid. So you set all the rows of the grid in editing state. It's not recommended way because it creates more problems.

The problem is the following. If you starts inline editing then jqGrid saves the original values from all editing rows inside of internal savedRow parameter which is array of original values of all editing rows. During inline editing the user can make some changes in any from the editable fields, but the user can cancel the changes by pressing Esc key. In other words jqGrid have to hold both old values and the current (not yet saved) modified values. If the user clicks on the column header then jqGrid sort by the column by default. Sorting means re-filling the current page of the grid. It's unclear whether the current editable rows should be saved or discarded. So the sorting are typically prohibited during inline editing. The same problem exist with searching.

If you want to allow searching during inline editing and if you need to save the data then you have to call saveRow in the loop inside of beforeSearch callback of filterToolbar. Exactly like you explicitly calls editRow for all rows inside of loadComplete you have to call saveRow for all rows inside of beforeSearch before trigger of reloadGrid.

One more remark to your code. It seems to me that the last row of the grid have special meaning - it contains the footer information. You set ireg-jqgrid-lastrow class on the row inside of gridComplete. The row will be not editable. Such scenario seems to me could be implemented in another way in jqGrid. You can add footerrow: true option in the grid. It add separate div below of the main grid, but all looks very close to the picture which you included. The main difference exist in separation of the main data from the footer. You can use footerData method to will the data in the footer or you can use userDataOnFooter: true option. jqGrid will the footer automatically with the data from userdata part of the data returned from the server. See the old answer and this one or this one for the corresponding demos and implementation details.



回答2:

SOLUTION:- I have implemented loadonce: true

oGrid.jqGrid('filterToolbar', { stringResult: true, defaultSearch: 'cn', //groupOp: 'OR',
    beforeSearch: function () {

        var oRules = new Array();
        var postdata = $('#tbLots').jqGrid('getGridParam', 'postData'), 
            oCustFilter = $.parseJSON(postdata.filters), colName, searchStr, operator, groupOperator = '';
        for (var i = 0; i < oCustFilter.rules.length; i++) {
            groupOperator = oCustFilter.groupOp;
            searchStr = oCustFilter.rules[i].data;
            colName = oCustFilter.rules[i].field;
            operator = oCustFilter.rules[i].op;

            oRules.push({ field: colName, op: operator, data: searchStr });
        }

        var oFilter = { groupOp: groupOperator, rules: oRules };
        $.extend(postdata, { filters: JSON.stringify(oFilter) });
        $('#tbLots').jqGrid('setGridParam', { search: true, postData: postdata });
        //$('#tbLots').trigger("reloadGrid", [{ page: 1}]);
    }

    /*here is the code, what you taught me to do*/
    var l_oIds = oGrid.jqGrid('getDataIDs'), i;
    for (i = 0; i < l_oIds.length; i++) {
        oGrid.jqGrid('saveRow', l_oIds[i], false, 'clientArray');
    }

    //reloading grid after saverow
    $('#tbLots').trigger("reloadGrid", [{ page: 1}]);

    return true;
});