当脚本使用 ajax 从数据库中检索保存的设置并使用它来填充 jqGrid 布局设置时。那是它进入无限循环的时候。经过一些研究,结果发现“groupingGroupBy”函数(在 jqGrid 源代码中)使用“reloadGrid”触发器,它与 jqGrid 的“beforeRequest”事件不能很好地混合。我欢迎更好的建议。谢谢...
这是代码...
$('#' + jqgridSpreadsheetId).jqGrid({
url: jqgridWebUrl,
datatype: 'json',
mtype: 'POST',
postData: { WhichJqgridTemplate: jqgridWhichTemplate },
jsonReader: { repeatitems: false },
colNames: ['', 'Id', 'Stock Number', 'VIN', 'Year', 'Make', 'Model', 'Trim', 'Mileage', 'Purchase Price', 'Stock Date', 'Repair Cost', 'Total Cost', 'Days In Inventory', 'Hidden-Inventory-Tracker-Location-Id', 'Inventory Tracker Location', 'Category', 'Links'], //Display Text in Column Header...
colModel: [
//jsonmap --> http://stackoverflow.com/questions/16396229/use-jqgrid-action-formatter...
// --> http://stackoverflow.com/questions/6989608/jqgrid-inline-edit-rows-and-data-not-lining-up...
// --> http://stackoverflow.com/questions/6364473/using-the-jsonmap-property-of-jqgrid-colmodel-with-untyped-json
//action-delete --> http://stackoverflow.com/questions/14732234/how-to-delete-row-in-jqgrid...
//In this case, use "sorttype" property in "colModel" for it to work when "loadonce" is set to true...
//formatter doc --> "http://www.trirand.com/jqgridwiki/doku.php?id=wiki:predefined_formatter&s[]=cell&s[]=formatter"...
//formatter hyperlink --> Stackoverflow posting was said to use formatter's function declaration instead of formatter's "showlink" followed by "formatoptions"...
// --> (Old Link) - http://stackoverflow.com/questions/5010761/linking-from-a-column-value-in-jqgrid-to-a-new-page-using-get...
// --> (New Link) - http://stackoverflow.com/questions/14529358/jqgrid-need-hyperlink-need-to-capture-value-through-jquery/14537512#14537512...
// --> (New Link) - http://www.trirand.com/jqgridwiki/doku.php?id=wiki:custom_formatter...
// --> Reasons are --> 1) far simpiler to use formatter for reading/writing and 2) much quicker and better performance...
{
jsonmap: function (o) { return ''; }, name: 'actDelete', index: 'actDelete', width: 40, align: 'center', sortable: false, hidedlg: true, formatter: 'actions', //"hidedlg" is use to hide the hidden column in "Column Chooser"...
formatoptions: {
keys: false, editbutton: false,
//http://stackoverflow.com/questions/11897649/cant-refresh-jqgrid-with-loadonce-true... (This show us how to reload jqGrid on edit/delete/add, the easy way, when using loadonce:true)...
delOptions: {
url: jqgridWebUrl,
mtype: 'POST',
onclickSubmit: function (objects, rowid) { return { WhichJqgridTemplate: jqgridWhichTemplate, WebpageVehicleVin: $(this).getCell(rowid, jqgridColumnIdVin), WebpageReason: $('textarea[id=#' + jqgridDialogDeleteTextareaId + ']').val() } },
width: 600,
errorTextFormat: function (response) { return "<div style='text-align:center;padding:3px 0px 3px 0px;'>Unable to delete vehicle from Inventory due to an internal error</div>"; },
beforeShowForm: function ($form) {
//http://stackoverflow.com/questions/10035911/jqgrid-inline-delete-selected-row-selrow-is-incorrect... (showed how to use "rowIdOfDeletedRow" in inline-delete dialog)...
//http://stackoverflow.com/questions/6913618/jqgrid-custom-delete-dialog-message... (showed how to customize the inline-delete's message)...
var rowIdOfDeletedRow = $('#DelData>td:nth-child(1)').text();
//Override delete wording message w/ custom message...
$('td.delmsg', $form[0]).html("<div style='padding-top:5px;text-align:center;'>Delete "" + $(this).getCell(rowIdOfDeletedRow, jqgridColumnIdYear) + " " + $(this).getCell(rowIdOfDeletedRow, jqgridColumnIdMake) + " " + $(this).getCell(rowIdOfDeletedRow, jqgridColumnIdModel) + " " + $(this).getCell(rowIdOfDeletedRow, jqgridColumnIdTrim) + "" vehicle record?</div>");
//Check to see if textarea exists, if not then create one...
if ($('table.DelTable tr:last td textarea[id=#' + jqgridDialogDeleteTextareaId + ']').length == 0) {
$('table.DelTable tr:last').after('<tr><td style="padding-bottom:10px;vertical-align:top;">Reasons: <textarea id="#' + jqgridDialogDeleteTextareaId + '" rows="2" cols="20" style="width:400px;height:60px;" /></td></tr>'); //display:table-cell;vertical-align:top;...
} else { $('textarea[id=#' + jqgridDialogDeleteTextareaId+']').val(''); }
},
resize: false,
}
},
search: false
}, //"hidedlg" is use to hide the hidden column in "Column Chooser"... //"search" is use to hide the field in search dialog...
{ jsonmap: function (o) { return o.cell[0]; }, name: 'Id', index: 'Id', sortable: false, width: 0, align: 'left', hidden: true, hidedlg: true, search: false }, //"search" is use to hide the field in search dialog, "hidedlg" is use to hide the hidden column in "Column Chooser"...
{ jsonmap: function (o) { return o.cell[1]; }, name: 'StockNumber', index: 'StockNumber', sorttype: 'text', align: 'center', searchoptions: { sopt: ['eq', 'ne'] } },
{ jsonmap: function (o) { return o.cell[2]; }, name: 'Vin', index: 'Vin', sorttype: 'text', width: 190, align: 'center', searchoptions: { sopt: ['eq', 'ne'] } },
{ jsonmap: function (o) { return o.cell[3]; }, name: 'Year', index: 'Year', sorttype: 'int', align: 'center', searchoptions: { sopt: ['eq', 'ne'] } },
{ jsonmap: function (o) { return o.cell[4]; }, name: 'Make', index: 'Make', sorttype: 'text', align: 'center', searchoptions: { sopt: ['eq', 'ne'] } },
{ jsonmap: function (o) { return o.cell[5]; }, name: 'Model', index: 'Model', sorttype: 'text', align: 'center', searchoptions: { sopt: ['eq', 'ne'] } },
{ jsonmap: function (o) { return o.cell[6]; }, name: 'Trim', index: 'Trim', sorttype: 'text', align: 'center', searchoptions: { sopt: ['eq', 'ne'] } },
{ jsonmap: function (o) { return o.cell[7]; }, name: 'Mileage', index: 'Mileage', sorttype: 'int', align: 'center', formatter: 'number', formatoptions: { decimalSeparator: '', thousandsSeparator: ',', decimalPlaces: 0, defaultValue: '0' } },
{ jsonmap: function (o) { return o.cell[8]; }, name: 'PurchasePrice', index: 'PurchasePrice', sorttype: 'currency', align: 'center', formatter: 'currency', formatoptions: { decimalSeparator: '.', thousandsSeparator: ',', decimalPlaces: 2, defaultValue: '0.00', prefix: '$', suffix: '' } },
{ jsonmap: function (o) { return o.cell[9]; }, name: 'StockDate', index: 'StockDate', sorttype: 'date', align: 'center', formatter: 'date', formatoptions: { newformat: 'm/d/Y' } }, //"formatter" and "formatoptions" is required for date sorting to works properly...
{ jsonmap: function (o) { return o.cell[10]; }, name: 'RepairCost', index: 'RepairCost', sorttype: 'currency', align: 'center', formatter: 'currency', formatoptions: { decimalSeparator: '.', thousandsSeparator: ',', decimalPlaces: 2, defaultValue: '0.00', prefix: '$', suffix: '' } },
{ jsonmap: function (o) { return o.cell[11]; }, name: 'TotalCost', index: 'TotalCost', sorttype: 'currency', align: 'center', formatter: 'currency', formatoptions: { decimalSeparator: '.', thousandsSeparator: ',', decimalPlaces: 2, defaultValue: '0.00', prefix: '$', suffix: '' } }, /*summaryType:'sum' is needed for column grouping to work...*/
{ jsonmap: function (o) { return o.cell[12]; }, name: 'DaysInInventory', index: 'DaysInInventory', sorttype: 'int', align: 'center', formatter: 'number', formatoptions: { decimalSeparator: '', thousandsSeparator: ',', decimalPlaces: 0, defaultValue: '1' } },
{ jsonmap: function (o) { return o.cell[13]; }, name: 'InventoryTrackerLocationId', sortable: false, width: 0, align: 'left', hidden: true, hidedlg: true, search: false }, //"search" is use to hide the field in search dialog, "hidedlg" is use to hide the hidden column in "Column Chooser"...
{ jsonmap: function (o) { return o.cell[14]; }, name: 'InventoryTrackerLocation', index: 'InventoryTrackerLocation', sorttype: 'text', align: 'center', searchoptions: { sopt: ['eq', 'ne'] } },
{ jsonmap: function (o) { return o.cell[15]; }, name: 'Category', index: 'Category', sorttype: 'text', align: 'center', searchoptions: { sopt: ['eq', 'ne'] } },
//Links is not present in json data from the website, so we customize it here...
{ jsonmap: function (o) { return ''; }, name: 'Links', index: 'Links', sortable: false, width: 80, align: 'center', hidedlg: true, formatter: function (cellValue, options, rowObject) { return "<span style='text-decoration:underline;cursor:pointer;'>Links</span>" }, search: false } //"search" is use to hide the field in search dialog, "hidedlg" is use to hide the hidden column in "Column Chooser"...
],
pager: '#'+jqgridPagerId,
rowNum: 1000000000, //-1, //10, //06/13/2013 - It is reported that the use of "-1" broke jqGrid when loadonce:true is used. Alternatively, use the max # of rows...
//#rowList: //[5, 10, 20, 50], //Page size dropdown in footer - To show how many rows per page...
rowList: [], //Disable page size dropdown...
pgbuttons: false, //Disable page control like next, back button...
pgtext: null, //Disable pager text line like "Page 0 of 10"...
viewrecords: false, //Disable current view record text like 'View 1-10 of 100'...
caption: 'My Inventory',
width: jqgridLayoutWidth,
shrinkToFit: false, /* This is not reliable */
forceFit: false, /* This is not reliable, plus it it wouldn't work if shrinkToFit is set to false... */
autoWidth: false,
cellLayout: 0, /* This defaulted to 5, so we need to set it to 0 for custom css to works better */
height: 400,
sortable: false, /* Do not allow header-column to shift sideway.. Makes it harder for draggable Group-Header-Column features to work... */ /* Discontinued - This allows both 1) Moving columns sideway to other location fields and 2) for jqGrid Column Chooser Plugin / JQuery Multiselect Plugin to work... */
grouping: true, /* This allows row data to be group into row grouping... */
loadonce: false, /* 06/10/2013 - Set it to false from now on... It is learned that having loadonce:true is not worth the trouble when using search feature, delete feature, etc. so we're better off having client-side do both 1) jqGrid ajaxGridOption and 2) server-side querying to do the heavy work for us... */
//emptyrecords: "No records to display",
ajaxGridOptions: {
beforeSend: function (xhr) { ftnThrobblerAnimationBegin2(); },
complete: function (xhr) { ftnThrobblerAnimationEnd2(); },
error: function (xhr) { alert("An error had occurred, please try again or notify webmaster of this error"); ftnThrobblerAnimationEnd2(); }
},
loadComplete: function () {
JqgridSummarySpreadsheetDisplay();
JqgridGroupedColumnsFormatter();
},
//#loadBeforeSend: function (xhr, settings) { /*Notice: A pre-callback to modify the ajax request object (XMLHttpRequest - xhr) before it is sent. Use this to set custom headers etc. Returning false will cancel the request...*/ },
beforeRequest: function () {
//JqgridColumnChooserSavedBuildsRecordsSetup("INIT", "4444");
$('#' + jqgridSpreadsheetId).jqGrid('groupingGroupBy',
"Make,Model",
{
groupCollapse: true,
groupField: ['name']//,
//08/16/2013 - Appearantly, this "groupText" object is broken and doesn't allow adding "groupText"'s value to recursive grouped column's "groupText" starting with 2nd grouped Columns and after...
// - Use the "jqgridGroupedColumnsFormatter()" function instead under the jqGrid's "loadComplete" attribute...
//groupText: ["<span style='float:left;font-weight:bold;'>{0} - ({1})</span><span style='float:right;font-weight:bold;'> </span>"]
}
);
}
});
示例 1
$('#test').jqGrid({
//.....,
loadComplete: function() {
/* ... */
},
beforeRequest: function() {
/* ... */
},
grouping: true,
groupingView: {
groupField: ["Make","Model"],
groupCollapse: true
}
});
示例 2
$('#test').jqGrid({
//.....,
loadComplete: function() {
/* ... */
},
beforeRequest: function() {
$(this).jqGrid('setGridParam', {
grouping: true,
groupingView: {
groupField: ["Make","Model"],
groupCollapse: true
}
}); //.trigger('reloadGrid');
},
});
示例 3
$('#test').jqGrid({
//.....,
loadComplete: function() {
$(this).jqGrid('setGridParam', {
grouping: true,
groupingView: {
groupField: ["Make","Model"],
groupCollapse: true
}
}); //.trigger('reloadGrid');
},
beforeRequest: function() {
/* ... */
},
});
示例 4
$('#test').jqGrid({
//.....,
loadComplete: function() {
/* ... */
},
beforeRequest: function() {
/* ... */
},
beforeProcessing: function() {
$(this).jqGrid('setGridParam', {
grouping: true,
groupingView: {
groupField: ["Make","Model"],
groupCollapse: true
}
}); //.trigger('reloadGrid');
}
});
示例 5
var blockInfiniteLoopCounter = 0;
$('#test').jqGrid({
//.....,
loadComplete: function() {
/* ... */
},
beforeRequest: function() {
/* ... */
},
beforeProcessing: function() {
if (blockInfiniteLoopCounter == 0) {
blockInfiniteLoopCounter++;
$(this).jqGrid('setGridParam', {
grouping: true,
groupingView: {
groupField: ["Make","Model"],
groupCollapse: true
}
}).trigger('reloadGrid');
}
}
});
例 6
var $grid = $("#list");
$grid.jqGrid({
datatype: 'json',
url: 'MyInventory-Testcase2.json',
jsonReader: {
repeatitems: false,
id: "Id",
root: function (obj) { return obj; },
page: function () { return 1; },
total: function () { return 1; },
records: function (obj) { return obj.length; }
},
loadonce: true,
colNames: ['Client', 'Date', 'Amount', 'Tax', 'Total', 'Closed', 'Shipped via', 'Notes'],
colModel: [
{name: 'name', width: 65},
{name: 'invdate', width: 80, align: 'center', sorttype: 'date',
formatter: 'date', formatoptions: {newformat: 'd-M-Y'}, datefmt: 'd-M-Y',
searchoptions: { sopt: ['eq', 'ne', 'lt', 'le', 'gt', 'ge'] }},
{name: 'amount', width: 75, },
{name: 'tax', width: 52, },
{name: 'total', width: 65, },
{name: 'closed', width: 80, align: 'center', formatter: 'checkbox',
edittype: 'checkbox', editoptions: {value: 'Yes:No', defaultValue: 'Yes'},
stype: 'select',
searchoptions: {
sopt: ['eq', 'ne'],
value: 'true:Yes;false:No'
}},
{name: 'ship_via', width: 100, align: 'center', formatter: 'select',
edittype: 'select',
editoptions: {
value: 'FE:FedEx;TN:TNT;IN:Intim',
defaultValue: 'Intime'
},
stype: 'select',
searchoptions: {
sopt: ['eq', 'ne'],
value: 'FE:FedEx;TN:TNT;IN:Intim'
}},
{name: 'note', width: 100, sortable: false}
],
cmTemplate: {editable: true},
rowNum: 10,
rowList: [5, 10, 20],
pager: '#pager',
gridview: true,
ignoreCase: true,
rownumbers: false, //true,
sortname: 'invdate',
viewrecords: true,
sortorder: 'desc',
height: '100%',
caption: 'Set grouping dynamically',
beforeProcessing: function() {
//beforeRequest: function() {
//loadComplete: function() {
$(this).jqGrid('setGridParam', {
//grouping: true,
groupingView: { groupCollapse: true, groupField: ["name", "amount"] }
//}); //#.trigger('reloadGrid');
});
}
});
$("#dynamicGrouping").change(function () {
var groupingName = $(this).val();
if (groupingName) {
//$grid.jqGrid('groupingGroupBy', groupingName);
$grid.jqGrid('groupingGroupBy', groupingName, {
// groupField : [groupingName],
groupOrder : ['desc'],
groupColumnShow: [false],
//groupDataSorted : true,
groupCollapse: true
});
} else {
$grid.jqGrid('groupingRemove');
}
});