1

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.enter image description here

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... enter image description here

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;
    }
});
Rahul More
  • 615
  • 3
  • 13
  • 41

2 Answers2

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.

Community
  • 1
  • 1
Oleg
  • 220,925
  • 34
  • 403
  • 798
  • I implemented your suggestion in beforeSearch function (please refer my updated code). But, If you see, I have wrote a function afterRefresh which I used to clear the search box. This function get call when I click refresh button to clear search box and grid get refresh. But it doesn't retain the value. – Rahul More Sep 04 '15 at 08:26
  • @Rahul: Sorry, but I don't understand which problem you have currently. You wrote about problems with searching, but now you write some problem after Refresh of the grid because you call `clearToolbar`. Which problem you have now? Will be the modified data saved before filtering and one can see that jqGrid filters **modified** data? What problem you have with refreshing/reloading the grid? If you want that jqGrid *saves* the data before reloading then you have to include the same code which saves the data inside of `beforeRefresh` of cause. – Oleg Sep 04 '15 at 08:39
  • Actually I have problem of searching only. But I thought that refreshing the grid may be creating problem because I have not applied `loadonce: true`. So when I refresh the grid it goes back and refills the data. So I think its cancelling the effect of `saverow`. To bring your attention to this, I mention about reloading the grid. Apologize me for not mentioning in my previous comment. – Rahul More Sep 04 '15 at 09:35
  • @Rahul: Sorry, but you wrote in your question, that you use `loadonce: true` and you used `editurl: 'clientArray'`. If you don't use `loadonce: true` then you should **first save all editable rows** and reload the grid only after you get successful response from the server that the rows are successfully saved. So you will have to implement *another scenario*. In any way my main suggestion stay unchanged: *you have to implement manual triggering of saving of modified rows before any searching, reloading or sorting*. It explains *why* I don't recommend to start inline editing of multiple rows. – Oleg Sep 04 '15 at 09:46
  • No sir, I am not using `loadonce: true`. I suggest you that should I use `loadonce` to solve my problem because `loadonce` make data local. So my all rows are already editable, I just have to enter data into editable rows and after searching is complete when I again come to that rows in which I entered data. It should show the same data what I was entered before searching. – Rahul More Sep 04 '15 at 09:58
  • @Rahul: Sorry, but I still don't understand your current question. The text of your original question which I answered started with "I am using toolbar searching on local data (because I am using option loadonce: true)". Now you write "I am not using `loadonce: true`". So you asked now about **another scenario**. I still not understand why you want to start editing of multiple rows at the same time. Moreover I see now that you call `restoreRow` inside of `onSelectRow` if the user clicks on new row. It seems to me that call of`saveRow` and then `editRow` will more corresponds your requirements – Oleg Sep 04 '15 at 10:30
  • I am so sorry to confuse you. Actually this time, I tried this with removing `loadonce: true`, I forgot that I have posted question with `loadonce: true`. Please apologize me for making confusion. But the good news is problem is solved and I am pasted the code above. – Rahul More Sep 04 '15 at 10:39
  • 1
    @Rahul: The code which you posted contains call `oGrid.jqGrid('saveRow', l_oIds[i], false, 'clientArray');` with **local** saving and you do the calls **after** `reloadGrid``. So I'm not sure that it's final solution. In any way I'm glad to hear that the problem is solved. – Oleg Sep 04 '15 at 10:49
  • Yes. I did same before you mention. Thank you so much sir. Yours `saveRow` suggestion played as a imp role to solve this problem. Keep supporting like this. Take care. – Rahul More Sep 04 '15 at 11:30
0

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;
});
Rahul More
  • 615
  • 3
  • 13
  • 41