问题
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":" "
}
]
}
回答1:
You code have many important errors:
colModel
containsindex
properties which are different from the value ofname
for the same item. It's the main bug. You don't specified anysortname
option of jqGrid so the values ofindex
properties will be never seen by the server. If you useloadonce: true
thenindex
properties must be the same as the values ofname
properties. I recommend you don't includeindex
properties at all. In the caseindex
properties will be initialized with the values ofname
properties- You use wrong value of
id
property injsonReader
:id: "0"
. One use such value sometime in case ofrepeatitems: true
. In the case the row will be represented in JSON input as array. So0
value will be correct because in can be used as index in the array. In case of usagerepeatitems: false
the items represented rows of data in the JSON input are objects with named properties. So You should useid: "ID"
in your case. Moreover you don't need to include injsonReader
the properties which value are default (root:"rows"
,page: "page"
) and so on. - The next problem is the usage of unconditional
reloadGrid
inside ofloadComplete
. You should understand thatloadComplete
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 ofreloadGrid
inside ofloadComplete
is bad from another point of view. If you triggerreloadGrid
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 ofsetTimeout
with some small time interval like50
ms. - 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.
- 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

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:
- One don't see any flicker after displaying of the first (unsorted) grid;
- 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.
回答2:
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();
...
来源:https://stackoverflow.com/questions/16378544/jquery-jqgrid-not-sorting-on-client-side