JQuery jqgrid not sorting on client side
Asked Answered
R

3

5

The data loads fine into the grid, but it won't sort.

When I click in the table header, the sort arrows appear, but the data's not being sorted.

Thanks.

    $("#CompTable").jqGrid({ 
            url:'BomExplosionInJsonObj.asp'
        ,   datatype: 'json'
        ,   mtype: 'GET'
        ,   height: 400
        ,   colNames:['Part','Description','Src','Std Usage','Usage Inc Scrap','Rate Scrap','UOM','Item','Unit Cost','Stock']
        ,   colModel:[  {name:'COMP1_PART',index:'Part', width:120}
                                ,   {name:'WSCOMPDESC',index:'Desc', width:300}
                                ,   {name:'WSCOMPSRC',index:'Src', width:10}
                                ,   {name:'COMPUSAGE',index:'Usage', width:80, align:"right",sorttype:"float"}
                                ,   {name:'WSGROSSQTY',index:'TotUsage', width:80, align:"right",sorttype:"float"}
                                ,   {name:'COMPRATE_SCRAP',index:'Rate Scrap', width:80, align:"right",sorttype:"float"}
                                ,   {name:'COMPBASIC_UNIT',index:'UOM', width:20}
                                ,   {name:'COMP1_ITEM',index:'Item', width:20}
                                ,   {name:'WSCOMPUNITCOST',index:'UnitCost', width:80, align:"right",sorttype:"float"}
                                ,   {name:'WSCOMPQTYSTOCK',index:'Stock', width:80, align:"right",sorttype:"float"}
                            ]
        ,   jsonReader: {
                root:"rows"
            ,   page: "page"
            ,   total: "total"
            ,   records: "records"
            ,   repeatitems: false
            ,   id: "0"
            }
        ,   multiselect: false
        ,   caption: "Bom Detail"
        ,   rowNum: 10000
        ,   autoencode: true
        ,   loadonce: true
        ,   sortable: true
        ,   loadComplete: function() {jQuery("#CompTable").trigger("reloadGrid");}// Call to fix client-side sorting
    });
});

JSON Data being returned (as read from firebug).

    {
     "total":"1"
    ,"page":"1"
    ,"records":"2"
    , "rows":
      [
       {"ID":1,"WSCOMPDESC":"ZYTEL E101L BLK MOUL ","WSCOMPUNITCOST":7.08,"WSCOMPSRC":"P ","WSCOMPQTYSTOCK":75,"COMPBASIC_UNIT":"KG ","COMPUSAGE":0.0034,"COMPRATE_SCRAP":0,"WSGROSSQTY":0.0034,"COMP1_PART":"1180019 ","COMP1_ITEM":" "
       },
       {"ID":2,"WSCOMPDESC":"INSERT ","WSCOMPUNITCOST":1.89,"WSCOMPSRC":"P ","WSCOMPQTYSTOCK":400,"COMPBASIC_UNIT":"EA ","COMPUSAGE":2,"COMPRATE_SCRAP":0,"WSGROSSQTY":2,"COMP1_PART":"4OWE195689\/ISS 2 ","COMP1_ITEM":" "
       }
      ]
    }
Reversal answered 4/5, 2013 at 20:14 Comment(0)
Q
16

You code have many important errors:

  1. colModel contains index properties which are different from the value of name for the same item. It's the main bug. You don't specified any sortname option of jqGrid so the values of index properties will be never seen by the server. If you use loadonce: true then index properties must be the same as the values of name properties. I recommend you don't include index properties at all. In the case index properties will be initialized with the values of name properties
  2. You use wrong value of id property in jsonReader: id: "0". One use such value sometime in case of repeatitems: true. In the case the row will be represented in JSON input as array. So 0 value will be correct because in can be used as index in the array. In case of usage repeatitems: false the items represented rows of data in the JSON input are objects with named properties. So You should use id: "ID" in your case. Moreover you don't need to include in jsonReader the properties which value are default (root:"rows", page: "page") and so on.
  3. The next problem is the usage of unconditional reloadGrid inside of loadComplete. You should understand that loadComplete will be executed on every reloading of the grid (event on local reloading). So it would be wrong making permanent reloading of grid. Moreover usage of reloadGrid inside of loadComplete is bad from another point of view. If you trigger reloadGrid the event will be executed * immediately*, but the grid is not in processing of previous loading. So it would be more correct to trigger reloading inside of setTimeout with some small time interval like 50 ms.
  4. The last recommendation is usage of K&R (Kernighan and Ritchie's) style of writing of the code. It's not so important which style of formatting of the code you use in another computer language and it's not important which one you personally find the most nice to read. JavaScript has it's own rights. One from there is automatic semicolon insertion (see here for example). If you follow K&R you will never have any problems with automatic semicolon insertion.
  5. I recommend you to use height: "auto" if you need display not so much rows and use column templates which could reduce the size of your code and simplify its management.

After described above changing the could will be something like below

var myFloatTemplate = { width: 80, align: "right", sorttype: "float" };

$("#CompTable").jqGrid({
    url: "BomExplosionInJsonObj.asp",
    datatype: "json",
    height: "auto",
    colNames: ["Part", "Description", "Src", "Std Usage", "Usage Inc Scrap", "Rate Scrap", "UOM", "Item", "Unit Cost", "Stock"],
    colModel: [
        {name: "COMP1_PART", width: 120},
        {name: "WSCOMPDESC", width: 300},
        {name: "WSCOMPSRC", width: 40},
        {name: "COMPUSAGE", template: myFloatTemplate},
        {name: "WSGROSSQTY", width: 120, template: myFloatTemplate},
        {name: "COMPRATE_SCRAP", width: 90, template: myFloatTemplate},
        {name: "COMPBASIC_UNIT", width: 60},
        {name: "COMP1_ITEM", width: 60},
        {name: "WSCOMPUNITCOST", template: myFloatTemplate},
        {name: "WSCOMPQTYSTOCK", template: myFloatTemplate}
    ],
    jsonReader: {
        repeatitems: false,
        id: "ID"
    },
    caption: "Bom Detail",
    rowNum: 10000,
    autoencode: true,
    loadonce: true,
    sortable: true,
    sortname: "COMP1_PART",
    //sortorder: "desc",
    loadComplete: function () {
        var $self = $(this);
        if ($self.jqGrid("getGridParam", "datatype") === "json") {
            setTimeout(function () {
                $self.trigger("reloadGrid"); // Call to fix client-side sorting
            }, 50);
        }
    }
});

The corresponding demo is here. Local sorting works and it displays the following results

enter image description here

UPDATED: Starting with version 4.12.0 free jqGrid fork of jqGrid, which I develop, support new forceClientSorting: true option. It works in combination with loadonce: true option and allows first load all the data from the server response, then sort the data locally and only then to display page of the data. It makes the trick with reloading of grid inside of setTimeout, started in loadComplete, described in the answer, not needed. One need just replace the above loadComplete code to one additional option forceClientSorting: true. The option forceClientSorting: true have additional two benefits:

  1. One don't see any flicker after displaying of the first (unsorted) grid;
  2. The performance of the grid is better, especially if it have many rows, because displaying the grid is much slowly as sorting. Moreover the trick with described in the old answer displays the grid, then delete the content (which is slowly too) and then one displays the sorted grid once more.
Qualify answered 5/5, 2013 at 9:47 Comment(1)
That's a great answer - thanks. The reloadgrid was something I found on another stackoverflow call about client-side sorting. Just started with jqgrid, so trying to understand how it all works. Thanks for your help.Reversal
G
0

The code you posted shows that the sorting will be done on the server not on the client. Your jqGrid will post sord and sidx parameters to allow you to do so as part of returning the data to the jqGrid.

Ex: C# MVC Controller code, where paging is also performed

public ActionResult GetGridData(string sidx, string sord, int page, int rows, bool _search, string filters)
{
 ...
 var pagedQuery = wholeDataSet.OrderBy(sidx + " " + sord).Skip((page - 1) * rows).Take(rows).ToList();
 ...
Googolplex answered 4/5, 2013 at 23:3 Comment(0)
J
0

Scanned through several answers and tried most of the options, but still the code which was working perfectly on local was not working on deployment. Finally I removed jquery links of dotnetcdn as well as googleapis and came to basics -

Opened source code on https://jqueryui.com/sortable/ and copied the src links

<script src="https://code.jquery.com/jquery-1.12.4.js"></script> 
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>

I am 68 yrs old and three days of struggle was too much. So sharing the answer on stackoverflow This is my return gift to all for helping me to learn coding

Judges answered 25/5, 2021 at 14:29 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.