2

当脚本使用 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 &quot;" + $(this).getCell(rowIdOfDeletedRow, jqgridColumnIdYear) + " " + $(this).getCell(rowIdOfDeletedRow, jqgridColumnIdMake) + " " + $(this).getCell(rowIdOfDeletedRow, jqgridColumnIdModel) + " " + $(this).getCell(rowIdOfDeletedRow, jqgridColumnIdTrim) + "&quot; 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');
               }
           });
4

1 回答 1

1

示例 2 有以下错误:您使用了 unneeded {...}。代码beforeRequest: function() {$('#test').jqGrid({'setGridParam', {...}});}应替换为beforeRequest: function() {$(this).jqGrid('setGridParam', {...});}.

我仍然认为使用静态 groupField值毫无意义。如果您在服务器上保存有关摸索的数据,我会认为服务器返回有关用户分组首选项的信息作为服务器响应的一部分更有意义。在这种情况下,您可以使用beforeProcessing回调来分析服务器响应的相应部分并设置jqGridgroupinggroupingView选项。

更新groupingSetup:可以通过在设置新groupingView选项后额外调用方法来修复示例 6 :

beforeProcessing: function () {
    var $this = $(this);
    $(this).jqGrid("setGridParam", {
        grouping: true,
        groupingView: {
            groupCollapse: true,
            groupField: ["name", "amount"]
        }
    });
    $this.jqGrid("groupingSetup");
}

我准备了相应的demo。我在演示中使用以下格式的 JSON 数据

{
    "groupField": ["name", "amount"],
    "rows": [
        { "id": "1",  "name": "test", ... },
        { "id": "2",  "name": "test2", ... },
        ...
        { "id": "12", "name": "test12", ... }
    ]
}

以及以下内容beforeProcessing

beforeProcessing: function (data) {
    var $this = $(this);
    $(this).jqGrid("setGridParam", {
        grouping: ($.isArray(data.groupField) && data.groupField.length > 0) ?
                  true :
                  false,
        groupingView: {
            groupCollapse: true,
            groupField: data.groupField //["name", "amount"]
        }
    });
    $this.jqGrid("groupingSetup");
}

所以我从服务器响应中获取分组字段([“name”,“amount”])。

于 2013-10-08T18:11:54.880 回答