views:

219

answers:

2

I am trying to figure out how to user the paging functionality of the jqGrid. Currently I am stuck on Page 1 of 4. No matter if I press the Next button or not. It just stays on 1.

I am using ASP.Net with a webservice to populate my JSON data. How do capture the event from the client to populate the property on the webservice to bring back the correct value?

Any help is appreciated.

+1  A: 

If one press "Next" button a new request will be send to the server. The request will contain page=2 and, for example, rows=10 parameters as a part of URL (if one want to get next 10 rows of the second page).

Your server code should read this parameters and send back the corresponding data rows. The JSON data send back from the server should look like following

{ 
  "total": "5", 
  "page": "2", 
  "records": "55",
  "rows" : [
    {"id" :"21", "cell" :["cell11", "cell12", "cell13"]},
    {"id" :"22", "cell" :["cell21", "cell22", "cell23"]},
      ...
    {"id" :"30", "cell" :["cell31", "cell32", "cell33"]},
  ]
}

(see http://www.trirand.com/jqgridwiki/doku.php?id=wiki:retrieving_data#json_data). So the data must contain the correct value for the page (page=2). In general it is possible, that now you have less data as before and you give back the page number 1 on the request to get the page number 2.

So I suggest that currently your server code don't give back the correct value of page in the output.

UPDATED: OK Jeff. I continue my answer in http://stackoverflow.com/questions/3169408/jqgrid-setgridparam-datatypelocal/3170652#3170652 and post how is promised a code how do server side paging, sorting and searching (or advanced searching).

First of all in the example I will not really implement sorting and searching and only simulate paging where you have problem now. The real paging, sorting and searching should be implemented as the corresponding SELECT statements to SQL database where the data exists. The sorting follow to the ORDER BY, searching to WHERE and paging to constructions like TOP(x), TOP(x) with LEFT OUTER JOIN or the usage of ROW_NUMBER() OVER(...) constructs. But these all are not the subject of your question. So I reduce all to the simple simulation of data paging.

I start with the code of the ASMX Web Method:

public JqGridData TestMethod (int page, int rows, string sidx, string sord,
    bool _search, string searchField, string searchOper, string searchString) {
    // for advance search use "string filters" instead of the last three parameters
    int recordsCount = 205;

    int startIndex = (page - 1) * rows;
    int endIndex = (startIndex + rows < recordsCount) ?
                   startIndex + rows : recordsCount; 
    List<TableRow> gridRows = new List<TableRow> (rows);
    for (int i = startIndex; i < endIndex; i++) {
        gridRows.Add (new TableRow () {
            id = i,
            cell = new List<string> (2) {
                string.Format("Name{0}", i), 
                string.Format("Title{0}", i)
            }
        });
    }

    return new JqGridData () {
        total = (recordsCount + rows - 1) / rows,
        page = page,
        records = recordsCount,
        rows = gridRows
    };
}

where classes JqGridData and TableRow are defined like following:

public class TableRow {
    public int id { get; set; }
    public List<string> cell { get; set; }
}
public class JqGridData {
    public int total { get; set; }
    public int page { get; set; }
    public int records { get; set; }
    public List<TableRow> rows { get; set; }
}

We skip any verification of input parameters of the TestMethod to make the code example more readable.

Now the client code:

$("#list").jqGrid({
    url: './MyTestWS.asmx/TestMethod',
    datatype: 'json',
    mtype: 'POST',
    ajaxGridOptions: { contentType: 'application/json; charset=utf-8' },
    serializeGridData: function (postData) {
        if (postData.searchField === undefined) postData.searchField = null;
        if (postData.searchString === undefined) postData.searchString = null;
        if (postData.searchOper === undefined) postData.searchOper = null;
        //if (postData.filters === undefined) postData.filters = null;
        return JSON.stringify(postData);
    },
    jsonReader: {
        root: function (obj) { return obj.d.rows; },
        page: function (obj) { return obj.d.page; },
        total: function (obj) { return obj.d.total; },
        records: function (obj) { return obj.d.records; }
    },
    // you can also use following more simple form of jsonReader instead:
    // jsonReader: { root: "d.rows", page: "d.page", total: "d.total",
    //               records: "d.records", id: "d.names" }
    colModel: [
        { name: 'name', label: 'Name', width: 250 },
        { name: 'title', label: 'Title', width: 250 }
    ],
    rowNum: 10,
    rowList: [10, 20, 300],
    sortname: 'name',
    sortorder: "asc",
    pager: "#pager",
    viewrecords: true,
    gridview: true,
    rownumbers: true,
    height: 250,
    caption: 'My first grid'
}).jqGrid('navGrid', '#pager', {edit: false, add: false, del: false, search: true});
//                {}, // use default settings for edit
//                {}, // use default settings for add
//                {}, // delete instead that del:false we need this
//                {multipleSearch : true} // enable the advanced searching
//                );

In the code I use the same technique like in http://stackoverflow.com/questions/3169408/jqgrid-setgridparam-datatypelocal/3170652#3170652 but the code of serializeGridData function is a little different. Because we use POST and not GET method to get the data from the server all input parameters of the web method must be always set. On the other side jqGrid set not always parameters searchField, searchOper and searchString, but only if _search=true. For example at the first load of jqGrid, the _search=false and searchField, searchOper and searchString are not defined in the postData. To fix the problem we initialize undefined parameters with null.

To implement sorting one needs to use sidx (sort index) and sord (sort direction: "asc" or "desc") parameters.

To implement searching one needs to use other parameters _search, searchField, searchOper, searchString.

During advanced searching instead of searchField, searchOper, searchString parameters the parameter filters must be used (see commented lines). The data must be decoded with respect of a JSON deserializer. So must be set multipleSearch : true in the jqgrid. The serializeGridData function should be replaced to

serializeGridData: function (postData) {
    if (postData.filters === undefined) postData.filters = null;
    return JSON.stringify(postData);
}

and the prototype of the web method should be changed to

public JqGridData TestMethod (int page, int rows, string sidx, string sord,
    bool _search, string filters)

to decode the parameter filters one can use such simple code:

if (_search && !String.IsNullOrEmpty (filters)) {
    JavaScriptSerializer serializer = new JavaScriptSerializer ();
    jqGridSearchFilter searchFilter =
        serializer.Deserialize<jqGridSearchFilter> (filters);
    // use the searchFilter here
}

where the class jqGridSearchFilter can be defined like following:

public class jqGridSearchFilterItem {
    public string field { get; set; }
    public string op { get; set; }
    public string data { get; set; }
}
public class jqGridSearchFilter {
    public string groupOp { get; set; }
    public List<jqGridSearchFilterItem> rules { get; set; }
}

I hope this information will be enough for you to implement any kind of jqGrid usage with respect of ASMX Web Method.

I used here a simplest data send from server to the client with additional id outside of the main data. If one of the columns which you have in the table is the id, you can a little reduce the data send to the server. See http://stackoverflow.com/questions/3054463/jqgrid-3-7-does-not-show-rows-in-internet-explorer/3061669#3061669 for more details.

Oleg
Thanks for the reply, however, I took out the page value altogether and it still isn't working. Currently my webservice is grabbing the entire recordset from the DB each time it is called. How can I capture the clicking of the "next" or "previous" buttons so I can pass something into my webservice?Any ideas?
Jeff V
Is there a way to capture what is being passed back to the webservice when I click on the "next" button?
Jeff V
To capture the HTTP traffic I use mostly Fiddler (see http://www.fiddler2.com/). The usage is very easy. The only problem you can have if server run locally. In the case you should replace in the URL localhost to the pseudo-name ipv4.fiddler.
Oleg
For data paging in typically the server responsible. In the new 3.7.x version of jqGrid it is do possible to use local paging. Try `loadonce:true` parameter of the jqGrid. You can also use `onPaging` event (see http://www.trirand.com/jqgridwiki/doku.php?id=wiki:events#list_of_events) which fires after clicking new page button.
Oleg
@Oleg: Thanks it is finally working. One small change I made was to the JSON reader. I'm not sure exactly why your example didn't work for me (might of been my object being returned from the WS). I changed it to: jsonReader: { root: "d.rows", page: "d.page", total: "d.total", records: "d.records", repeatitems: false, id: "d.names" },And then it started to work! Your example will help a lot of people. Thanks for seeing me through to the end.
Jeff V
@Jeff. You welcome! On http://www.trirand.com/blog/?page_id=393/help/asp-net-webservice-how-to-load-grid-from/#p18382 I promised you to help with the working example, so your problem must at the end works. About `jsonReader`: both ways must work. So the usage of JSON dot notation is absolutely OK. I wanted only give more variation in `jsonReader` compared to what I written before.
Oleg
A: 

Ok I'm answering this one as I took what Oleg had said above but figured out exactly what he meant.

My .ajax call in wrapped in a function that passes postdata as a parameter. I couldn't find any documentation on that parameter but I thought maybe that is where the page value was contained. As you can see I did an alert with postdata.page and low and behold I got a value (based off of the click of the next button).

So I created a parameter in my webservice called page (integer).

Just as a side note, you pass in a integer value from jQuery to your ASP.Net webservice like this:

data: "{'page':'" + postdata.page + "'}"

Below is the full function:

function processrequest(postdata) {
alert(postdata.page);
$(".loading").show();
$.ajax({
    type: "POST",
    data: "{'page':'" + postdata.page + "'}",
    datatype: "json",
    url: "../webServices/myTestWS.asmx/testMethod",
    contentType: "application/json; charset-utf-8",
    complete: function (jsondata, stat) {
        if (stat == "success") {
            var thegrid = jQuery("#list")[0];
            var jsonObject = (eval("(" + jsondata.responseText + ")"));
            thegrid.addJSONData(jsonObject.d);
            $(".loading").hide();
        } else {
            $(".loading").hide();
            alert("Error with AJAX callback");
        }
    }
});

}

Jeff V
In http://stackoverflow.com/questions/3151565/can-you-use-jqgrid-within-asp-net-using-a-webservice-and-javascript/3151997#3151997 I tried explain you don't use `$.ajax` and use `ajaxGridOptions: { contentType: 'application/json; charset=utf-8' }` instead. If you post code of your `testMethod` (it can return some test data directly in one return statement) I will change it to show how you can easy use jqGrid without the usage of `addJSONData`.
Oleg
Oleg, if you don't use .ajax to call your webservice how would you set it up using ajaxGridOptions? I was unable to find examples that clearly set this up.
Jeff V
Public Function testMethod() As myTest Dim myString As New myTest myString.records = 2 myString.total = 2 myString.page = 1 Dim myName As New names Dim myName2 As New names Dim myNamesList As New List(Of names) myName.name = "Jeff" myName.title = "Programmer" myName2.name = "Steve" myName2.title = "Programmer" myNamesList.Add(myName) myNamesList.Add(myName2) myString.rows = myNamesList Return myString End Function
Jeff V
@Oleg: I finally found some examples of how to use ajaxGridOptions to call my webservice. However I have an error now:"Message":"Invalid JSON primitive: _search. url: '../webServices/myTestWS.asmx/testMethod', datatype: 'json', ajaxGridOptions: { contentType: 'application/json; charset=utf-8' }, mtype: 'POST',What now?
Jeff V