在jqGrid中呈现之前,如何修改从AJAX调用返回的数据?

时间:2011-06-24 03:25:12

标签: jquery ajax jqgrid

背景

我从其他开发人员处获得了一些涉及显示搜索结果的不完整工作。他的方法是使用内联Javascript和jQuery将结果呈现在HTML表中,如下所示。

Grid using table and inline Javascript

我正在尝试完成这项工作,但我更愿意编写更少的代码并使用jqGrid,因为它包含排序功能,并使代码更整洁。让jqGrid显示结果很简单,但是将单选按钮放在空白列中比我想象的要难。

应用程序中jqGrid的版本是3.7.2。网格需要在左侧有单选按钮以供选择,以使内容与应用程序的其余部分保持一致。

我被困的地方

似乎没有办法在jqGrid中拥有未绑定的列。也就是说,每列似乎都需要基础数据中的字段。如果您没有虚拟字段,则行数据和列标题会变得不对齐。

我遇到了example(请参阅行编辑 - >自定义编辑),它返回数据中带有虚拟字段的JSON,然后修改网格数据以插入按钮。

我的偏好是没有虚拟数据,因为感觉很脏 :)我希望我的JSON只包含表示搜索结果所需的数据。所以我认为最好在脚本代码中添加虚拟字段,以便保持服务器端的代码清洁。

我试图在jqGrid渲染之前修改从AJAX调用返回的数据。我已经尝试挂钩loadComplete事件,但是当我修改数据时,它似乎已经渲染了。

我还尝试在success ajaxGridOptions字段options上挂钩,但这似乎完全覆盖了事件,jqGrid不会呈现数据。

如何在jqGrid呈现之前修改从Web服务调用返回的数据?

3 个答案:

答案 0 :(得分:2)

我设法弄清楚该怎么做。不要让 jqGrid 自动加载数据,而是需要手动执行请求,然后通过调用addJSONData加载它。

我的jqGrid在标记中定义如下:

<fieldset>            
    <div style="display:none" class="searchResults">
        <table id="eventSearchDialog-results">
        </table>
        <div id="eventSearchDialog-pager">
        </div>
    </div>
</fieldset>

我使用以下代码初始化网格:

// Initialize the grid
this._searchResults = this._dialog.find("#eventSearchDialog-results");
this._searchResults.jqGrid(
{
    datatype: "local",
    colNames: ['', 'Event Name', 'Event Type', 'Start Date', 'End Date', 'Location', 'Event Country', 'Sports'],
    colModel: [
                { name: 'selector', index: 'selector', width: 30 },
                    { name: 'EventName', index: 'EventName', formatter: jqgridCellFormatter, width: 150 },
                { name: 'EventType', index: 'EventType', formatter: jqgridCellFormatter, width: 120 },
                { name: 'StartDate', index: 'StartDate', formatter: jqgridCellFormatter, width: 100 },
                { name: 'EndDate', index: 'EndDate', formatter: jqgridCellFormatter, width: 100 },
                { name: 'Location', index: 'Location', formatter: jqgridCellFormatter, width: 100 },
                { name: 'EventCountry', index: 'EventCountry', formatter: jqgridCellFormatter, width: 100 },
                { name: 'Sports', index: 'Sports', formatter: jqgridCellFormatter }
                    ],
    rowNum: 10,
    rowList: [10, 20, 30],
    pager: this._dialog.find("#eventSearchDialog-pager"),
    pginput: true,
    sortname: 'EventName',
    viewrecords: true,
    sortorder: "asc",
    hidegrid: false,
    height: "auto",
    shrinkToFit: true,
    width: 630,
    jsonReader:
                    {
                        page: "pageIndex",
                        total: "pageCount",
                        records: "recordCount",
                        root: "rows",
                        repeatitems: true
                    },
    prmNames:
    {
        page: "pageIndex",
        rows: "pageSize",
        sort: "sortField",
        order: "sortOrder"
    }
}
);
// Set the data type to JSON, we don't do this in the options because it will cause a request to occur,
// but we do need it to be set to JSON so that the calls to addJSONData work later.
this._searchResults.jqGrid("setGridParam", { datatype: "json" });

我使用来自jQuery $.ajax()调用的数据加载网格,并在success事件处理程序中填充数据,然后使用addJSONData将其加载到jqGrid中。

我的JSON看起来像这样:

{
    "pageCount":1,
    "pageIndex":1,
    "recordCount":2,
    "rows":
    [
        {"id":3, "cell":["Stevens Event 2", "Commonwealth Games", "03/05/2011", "16/05/2011", "sersdfweqr", "New Zealand", ["Archery"]]},
        {"id":4, "cell":["Test - multiple sports", "Other", "01/05/2011", "30/06/2011", "Kobe", "Japan", ["Judo", "Karate", "Motor Sport", "Motorcycling", "Taekwondo"]]}
    ]
}

这是我的success处理程序:

success: function (data, textStatus, xhr) {
    // Pad data for our radio button column that has no corresponding field in the data
    for (var counter = 0; counter < data.rows.length; counter++) {
        data.rows[counter].cell.splice(0, 0, null);
    }

    thisEventSearchDialog._searchResults[0].addJSONData(data);
    thisEventSearchDialog._createRadioButtons();
},

jqGrid包含需要虚拟数据的单选按钮列。没有虚拟数据,行数据与标头不匹配。 enter image description here

答案 1 :(得分:0)

我之前的答案中的解决方案打破了排序,因此我提出了另一种解决方案。

因为jqGrid没有提供钩子来方便地修改数据,所以有必要删回一个级别并挂钩到jQuery。我用自己的方法替换了$.ajax()方法。首先,它检查操作是否是由jqGrid启动的操作,如果是,则填充数据,调用原始jqGrid success处理程序,然后将单选按钮添加到网格中。排序仍然有效,数据类型仍然是json,并且没有对addJSONData的手动调用,我仍然能够实现我之前的解决方案所需的功能。从本质上讲,制作这个小jQuery hack可以让我顺利通过,而不会使任何jqGrid黑客更糟糕。

// Set up $.ajax() hook for modifying the data before jqGrid receives it
if (!this._ajaxOverridden) {
    var oldAjax = $.ajax;
    $.ajax = function (options) {
        // Check whether this call is from jqGrid to our web service
        if (options.url == config.eventSearchUrl && options.success) {
            // Wrap the success event handler with our own handler that pads the data and creates the radio buttons
            var oldSuccess = options.success;
            options.success = function () {
                thisEventSearchDialog._padData(arguments[0]);
                oldSuccess.apply(this, arguments);
                thisEventSearchDialog._createRadioButtons();
            }
        }
        oldAjax(options);
    };
    this._ajaxOverridden = true;
}

答案 2 :(得分:0)

这是一个老问题,它可能不适用于所提及的jqGrid版本(3.7.2),但它似乎与此相关:How to "pre-process" an ajax response before displaying in jqGrid如果我是对的(关于然后正确答案是dataFilter参数的ajaxGridOption参数/函数。它对我有用。