jqGrid with Ajax data (JSON) : load data in grid using "url" parameter from azure database

Mohit picture Mohit · Apr 7, 2013 · Viewed 24.8k times · Source

I have one doubt with ajax implementation. I could find that "url" parameter need to be defined as "service_name1.azure-mobile.net/tables/" to fetch data to populate grid. But I need to add request header "X-ZUMO-APPLICATION" to define application key. To accomplish this, I think I have to make a httprequest with proper headers in a function and need to set reference of that function in some parameter of jqGrid to load data. Can you point out how is it possible to achieve?

Page on which jqGrid is used, starts with "https://service_name2.azure-mobile.net"

Here service_name1 is azure mobile service name and service_name2 is azure web service name and I have enabled CORS (cross object resource sharing) for service_name2 on mobile service service_name1.

Please let me know if any additional information is required

Updated code to make it work with Ajax call :

        jQuery("#list4").jqGrid({
        datatype: "json",
        url : 'https://mohit.azure-mobile.net/tables/Schedules',
        height: "auto",
        colNames: ['RowNo', 'RouteId', 'Area],
        colModel: [
                  { name: 'id', index: 'id', width: 50, sortable: false },
                  { name: 'RouteId', index: 'RouteId', width: 50, sortable: false, editable: true, editrules: { required: true} },
                  { name: 'Area', index: 'Area', width: 130, sortable: false, editable: true, editrules: { required: true} },
              ],
        rowList: [10, 20, 30],
        loadBeforeSend: function(jqXHR) {
                                            jqXHR.setRequestHeader('X-ZUMO-APPLICATION', 'mykey');
                                        },
        ajaxGridOptions: { contentType: "application/json" },
        postData: "",
        serializeGridData: function (data) {return JSON.stringify(data);},
        pager: '#pager1',
        viewrecords: true,
        caption: "Schedule Data",
        //loadonce: true,
        gridview: true
    });

Weird thing is, I am not able to capture this request using fiddler so I am capturing request using IE developer toolbar (using F12). I tried composing a request using fiddler, used GET with url'https://mohit.azure.net/tables/Schedules' and set header parameter as X-ZUMO-APPLICATION : appKey. I got proper response (expected JSON formatted table data) with this request. So I am feeling appended parameters are issue.

Update code part 2

    jQuery("#list4").jqGrid({
        datatype: "json",
        url : 'https://mohit.azure-mobile.net/tables/Schedules',
        height: "auto",
        colNames: ['RowNo', 'RouteId', 'Area'],
        colModel: [
                  { name: 'id', index: 'id', width: 50, sortable: false },
                  { name: 'RouteId', index: 'RouteId', width: 50, sortable: false, editable: true, editrules: { required: true} },
                  { name: 'Area', index: 'Area', width: 130, sortable: false, editable: true, editrules: { required: true} }
              ],
        rowList: [10, 20, 30],
        loadBeforeSend: function(jqXHR) {
                                            jqXHR.setRequestHeader('X-ZUMO-APPLICATION', 'myKey');
                                        },
        loadComplete: function () {
                                        //alert("OK");
                                  },
        loadError: function (jqXHR, textStatus, errorThrown) {
                                                                    alert('HTTP status code: ' + jqXHR.status + '\n' +
                                                                    'textStatus: ' + textStatus + '\n' +
                                                                    'errorThrown: ' + errorThrown);
                                                                     alert('HTTP message body (jqXHR.responseText): ' + '\n' + jqXHR.responseText);
                                                             },
        ajaxGridOptions: { contentType: "application/json", cache: true },
        postData: "",
        pager: '#pager1',
        viewrecords: true,
        caption: "Schedule Data",
        loadonce: true,
        gridview: true
    });

   var inlineparams = {
        restoreAfterSelect: false,
        add: true,
        edit: true,
        save: true,
        cancel: true,
        del: true
    };

    jQuery("#list4").jqGrid('navGrid', "#pager1", { edit: false, save: false, add: false, cancel: false, del: false });
    jQuery("#list4").jqGrid('inlineNav', "#pager1", inlineparams);       
}

Solution for loading data in grid with jqGrid version 4.4.5 using Ajax way

                       jQuery("#list4").jqGrid({
        datatype: "json",
        url : 'https://mohit.azure-mobile.net/tables/Schedules',
        height: "auto",
        colNames: ['RowNo', 'RouteId', 'Area'],
        colModel: [
                  { name: 'id', index: 'id', width: 50, sortable: false },
                  { name: 'RouteId', index: 'RouteId', width: 50, sortable: false, editable: true, editrules: { required: true} },
                  { name: 'Area', index: 'Area', width: 130, sortable: false, editable: true, editrules: { required: true} },
              ],
        rowList: [10, 20, 30],
        loadBeforeSend: function(jqXHR) {
                                            jqXHR.setRequestHeader('X-ZUMO-APPLICATION', 'myKey');
                                        },
        loadComplete: function () {
                                        //alert("OK");
                                  },
        loadError: function (jqXHR, textStatus, errorThrown) {
                                                                    alert('HTTP status code: ' + jqXHR.status + '\n' +
                                                                    'textStatus: ' + textStatus + '\n' +
                                                                    'errorThrown: ' + errorThrown);
                                                                     alert('HTTP message body (jqXHR.responseText): ' + '\n' + jqXHR.responseText);
                                                             },
        ajaxGridOptions: { contentType: "application/json", cache: true },
        postData: "",
        pager: '#pager1',
        viewrecords: true,
        caption: "Schedule Data",
        loadonce: true,
        jsonReader: {repeatitems: false},
        gridview: true
    });

Answer

Oleg picture Oleg · Apr 7, 2013

First of all I think the the title of the question "how to call custom function to load data instead of using “url” parameter" is incorrect. I think that what you describe could be implemented per standard Ajax call, but using JSONP type instead of JSON.

To set custom HTTP/HTTPS headers you can use setRequestHeader method of inside of loadBeforeSend callback of jqGrid. See the answer. In case of editing of grid inside of beforeSend callback of jQuery.ajax call which do jqGrid. You can use ajaxEditOptions or ajaxRowOptions option of jqGrid (depend on editing mode which you use) to set the beforeSend callback of jQuery.ajax call. Alternatively you can use headers option of jQuery.ajax (one can set it in jqGrid using ajaxGridOptions, ajaxEditOptions or ajaxRowOptions).

I think that if you configured correctly Cross-Origin Resource Sharing (CORS) (see here) you could use JSONP in jqGrid to load the data. See examples here, here and here.

UPDATED: I can't test the code, but I think you should change some options/callbacks which you use:

  1. remove serializeGridData is you use postData: ""
  2. change datatype: "json" to datatype: "jsonp"
  3. change ajaxGridOptions: { contentType: "application/json" } to ajaxGridOptions: { contentType: "application/json", cache: true }

If it will not help I would recommend you to use tools like Fiddler to trace HTTPS traffic. You will need additionally activate tracing of HTTPS inside the tool (see the documentation).

UPDATED 2: It seems that in case of usage Windows Azure Mobile Services you can use datatype: "json" and url: 'https://<service_name1>.azure-mobile.net/tables/<TableName>'. To get the data it's important only to use

ajaxGridOptions: { contentType: "application/json" },
postData: "",
jsonReader: {
    repeatitems: false,
    root: function (obj) {
        return obj;
    }
}

To be able to modify the data with respect of inline editing you should produce HTTP request having

PATCH https://mstrans.azure-mobile.net/tables/<TableName>/<TableItemId> HTTP/1.1
Content-Type: application/json

in the HTTP header and JSON data with the modified row, but without unneeded oper parameter. To do this you can

editurl: "https://mohit.azure-mobile.net/tables/Schedules",
ajaxRowOptions: { contentType: "application/json" },
serializeRowData: function (postData) {
    if (postData != null && postData.oper) {
        delete postData.oper;
    }
    return JSON.stringify(postData);
}

The code above will do almost all what one need with the exception that it will be used as URL "https://mohit.azure-mobile.net/tables/" instead of "https://mohit.azure-mobile.net/tables//".

To make the last step one can modify url inside of for example oneditfunc callback of inlineparams or better jqGridInlineEditRow event:

var inlineparams = {
    editParams: { mtype: "PATCH", keys: true},
    addParams: {
        addRowParams: { mtype: "POST", keys: true }
    }
};

jQuery("#list4").bind("jqGridInlineEditRow", function (e, rowid, options) {
    if (options.mtype === "PATCH") {
        options.url = "https://mohit.azure-mobile.net/tables/Schedules/" +
            encodeURIComponent(rowid);
    }
});