1

With Oleg's help, I'm really making some progress on using jqGrid. The next area of confusion is around what happens after the data is edited and sent to the server for update. If I use inline or form edits, the data looks great in the grid. But when I click the Reload Grid button in the nav, the data is reverted back to their original values. I've read a lot of posts about using the "reloadGrid" but it's not working; probably because of user error.

I'm trying to figure out if the correct approach is to update the grid manually after an edit. I really don't want to go back to the server to get the data again. I was thinking of using the afterComplete event.

Any advice is greatly appreciated. Thank you very much.

Update: I thought I had everything working. If I leave the page, and reload the data, the original data appears in the grid. The data is cached. If I turn on the caching options to always load from the server (in the IE developer bar), it works. The correct data is displayed. Is it normal for the data to be cached like that even if I recreate the jqGrid the next time the page loads?

Update #2: In looking at this demo, http://www.trirand.com/blog/jqgrid/jqgrid.html, select Row Editing and Basic Example. Click Edit row 13, make a change and then save the changes. Click the Reload Grid in the navigator toolbar and the data refreshes back. Is there a way to avoid this? I know I'm missing something.

$.getJSON('FileServices/Get/JSA/' + id, function (data) {
    $("#header_id").html(data.header.Id);
    $('#dateAdded').datepicker();
    $('#number').val(data.header.Number);

    onclickSubmitLocal = function (options, postdata) {
    },
    onAfterComplete = function (response, postdata, formid) {                    
        $("#list").setCell(postdata.id, "Step_Number", postdata.Step_Number);
    },
    editSettings = {                              
        recreateForm: true,
        width: 400,
        mtype: "PUT",
        jqModal: true,
        reloadAfterSubmit: false,
        closeOnEscape: true,
        savekey: [true, 13],
        closeAfterEdit: true,
        viewPagerButtons: false,
        editData: { SomeExtraData: function () { return $('#header_id').val(); } },
        afterComplete: onAfterComplete,
        onclickSubmit: onclickSubmitLocal
    },
    addSettings = {
        recreateForm: true,
        width: 400,
        mtype: "POST",
        jqModal: true,
        reloadAfterSubmit: false,
        savekey: [true, 13],
        closeOnEscape: true,
        closeAfterAdd: true,
        editData: { SomeExtraData: function () { return $('#header_id').val(); } },
        onclickSubmit: onclickSubmitLocal
    };

    $("#list").jqGrid({
        url: 'FileServices/GetList/JSA',
        data: data.details,
        editurl: 'FileServices/Save/JSADetail',
        datatype: 'local',
        ajaxRowOptions: { contentType: "application/json", type: "PUT", asyc: true },       
        serializeRowData: function (data) {
            return JSON.stringify(data);
        },
        gridComplete: function () {
            var ids = jQuery("#list").jqGrid('getDataIDs');
            for (var i = 0; i < ids.length; i++) {
                var cl = ids[i];
                be = "<input style='height:22px;width:20px;' type='button' value='E' onclick=\"jQuery('#list').editRow('" + cl + "');\" />";
                se = "<input style='height:22px;width:20px;' type='button' value='S' onclick=\"jQuery('#list').saveRow('" + cl + "');\" />";
                ce = "<input style='height:22px;width:20px;' type='button' value='C' onclick=\"jQuery('#list').restoreRow('" + cl + "');\" />";
                jQuery("#list").jqGrid('setRowData', ids[i], { act: be + se + ce });
            }

            $("#list").jqGrid('setGridParam', {}).trigger("reloadGrid");
        },
        loadComplete: function (data) {
            var det = $("#details");
            $("#list").setGridWidth(det.width() - 18, true);
        },
        colNames: ['Actions', 'Header_Id', 'Id', 'Step Number', 'Step Description', 'H', 'C', 'S'],
        colModel: [
          { name: 'act', index: 'act', width: 75, sortable: false },
          { name: 'Header_Id', editable: true, index: 'Header_Id', width: 20, sortable: false, hidden: true },
          { name: 'Id', editable: true, index: 'Id', width: 30, sortable: false, hidden: true },
          { name: 'Step_Number', editable: true, index: 'Step_Number', align: 'center', width: 50, fixed: true, resizable: false, sortable: false, title: false, cellattr: function (rowId, tv, rawObject, cm, rdata) { return 'style="font-weight: bold: true; white-space: normal; vertical-align: middle;' } },
          { name: 'Step_Description', editable: true, index: 'Step_Description', edittype: 'textarea', editoptions: { rows: '4', cols: '40' }, sortable: false, width: 400, cellattr: function (rowId, tv, rawObject, cm, rdata) { return 'style="white-space: normal; vertical-align: top;' } },
          { name: 'H', index: 'H', width: 200, sortable: false, cellattr: function (rowId, tv, rawObject, cm, rdata) { return 'style="white-space: normal; vertical-align: top;' } },
          { name: 'C', index: 'C', width: 200, sortable: false, cellattr: function (rowId, tv, rawObject, cm, rdata) { return 'style="white-space: normal; vertical-align: top;' } },
          { name: 'S', index: 'S', width: 0, sortable: false, hidden: true }
        ],
        pager: '#pager',
        rowNum: 5,
        rowList: [5, 10, 15, 20, 25, 30, 50],
        sortname: 'Id',
        height: 'auto',
        rownumbers: true,
        autowidth: true,
        forceFit: true,
        shrinkToFit: true,
        sortorder: 'asc',
        viewrecords: true,
        gridview: true,
        hidegrid: false,
        caption: ''
    }).navGrid("#pager", { add: true, edit: true, del: false, search: false }, editSettings, addSettings, {}, {}, {});

    $.extend($.jgrid.defaults, {
        datatype: 'json',
        ajaxGridOptions: { contentType: "application/json" }
    });

    $.extend($.jgrid.edit, {
        ajaxEditOptions: { contentType: "application/json" },
        recreateForm: true,
        type: "PUT",
        closeAfterEdit: true,
        closeOnEscape: true,
        serializeEditData: function (postData) {
            return JSON.stringify(postData);
        }
    });
});

and

[WebInvoke(Method = "PUT", UriTemplate = "/Save/JSADetail", BodyStyle = WebMessageBodyStyle.Wrapped, RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
public string UpdateJSADetail(int Header_Id, int Id, string Step_Number, string Step_Description, string oper, string id)
{
    JSA.Detail detail = new JSA.Detail();

    detail.Id = Id;
    detail.Step_Number = Step_Number;
    detail.Step_Description = Step_Description;

    detail.Update();

    return "Ok";
}
DrZ
  • 181
  • 5
  • 22
  • The problem is in the usage of Ajax with the HTTP GET and the response which has no information how the data should be cached. IE interpret the case as it can just get the old data from the cache till the IE will be restarted the next time. Read more in my answer. – Oleg Sep 17 '11 at 20:14
  • To your Update #2: I think it's very special case. It the date which you changed on the demo side really would be saved in the database the database will be full garbage in very short time. So I suppose, that the server part just discard the changes and the changes will be done only on the client side. In case of form editing the setting `reloadAfterSubmit: false` will be sure used. I think the case have nothing common with your case. It just looks close to your case. – Oleg Sep 17 '11 at 23:37
  • Hi Oleg. In my case, I am writing to the database and it's successful. If I go back to my "load" page and select the item again to load, the grid loads the correct (and newly updated) data. When I click the grid's reload button OR select 10 records to be displayed instead of 5, the data reverts back. It seems that the data behind the grid isn't being updated when I make edits. Where does jqGrid get the data to be displayed after a change? It's not getting it from the database. When I update the database, do I also need to update the data behind the grid? Thank you. – DrZ Sep 21 '11 at 22:18
  • Could you provide you code of jqGrid which you use? Do you have the problem with old data only in one specific column or in the row in general. Which response send the server? Do you use some other event handlers like `afterSubmit` for example? – Oleg Sep 21 '11 at 22:33
  • Hi Oleg. It's in all the columns that are editable. I've played around with a couple of the other event handlers in the event I have to manually update the data. – DrZ Sep 21 '11 at 22:45
  • 1
    You code contain both inline editing and form editing. Do you have the problem with the saving of the data in both case? Which data send the server as the response on the row saving? – Oleg Sep 21 '11 at 22:56
  • Both behave the same way. I'm not sure what you mean by your last sentence. I added my web service call in the question above. Does the web service have to return a specific value? – DrZ Sep 21 '11 at 23:09
  • I mean just the following: if the server would return some error HTTP code the data will not saved on the client side. If for example any exception are in the server code the server response will have error HTTP code automatically. One more *very strange* place in your code is `$("#list").jqGrid('setGridParam', {}).trigger("reloadGrid");` inside of `gridComplete`. Why you need trigger reloading of the grid during the loading of it? – Oleg Sep 21 '11 at 23:24
  • Thanks Oleg. I removed the code above (left over from other experiments) and that didn't make a difference. There are no errors (client side or server) that I can see. I'm still looking... – DrZ Sep 21 '11 at 23:33
  • Could you set breakpoint on [the line](https://github.com/tonytomov/jqGrid/blob/v4.1.2/js/grid.formedit.js#L724) of the code and examine the current values of `postdata[idname]` and `postdata`. In case of inline editing [another line of code](https://github.com/tonytomov/jqGrid/blob/v4.1.2/js/grid.inlinedit.js#L240) should be important. – Oleg Sep 21 '11 at 23:41
  • postdata[idname] is "1". When I look at postdata, it is correct. It contains the new value of the field (Step_Number). – DrZ Sep 21 '11 at 23:52
  • In any way you should just use original (non-minimized) src version of jqGrid and debug the code over two lines which I mentioned in my previous comments. If all parameters of `setRowData` are correct then you should debug inside of `setRowData` method. The code of [setRowData](https://github.com/tonytomov/jqGrid/blob/v4.1.2/js/grid.base.js#L2648) is not long, so I hope you will localize the problem very quickly. – Oleg Sep 22 '11 at 08:51

2 Answers2

2

Are you verified that the data are changed in the database after saving in jqGrid? Do you verified in Fiddler or Firebug that wrong data come from the server? It can be that you have some caching problem.

In comments to your other question I strict recommended you don't load the data manually with $.getJSON. If you do this you should in any way use $.ajax with cache: false parameter or at least set cache: false option as the defaults options. You can use $.ajaxSetup to do this. By the way the problem with the default cache: true value typically exist only in Internet Explorer. If you repeat your experiments with the grid editing in another browser and you will see no problem in the browser you can be sure that you problem is the cache: false option.

One more way to solve the same caching problem could be to set "Cache-Control: max-age=0" in the HTTP header of the server response which provide the data for the grid. In WCF you can do this with

WebOperationContext.Current.OutgoingResponse.Headers.Set (
    HttpResponseHeader.CacheControl,
    "max-age=0");

in other ASP.NET with respect of

HttpContext.Current.Response.AddHeader ("Cache-Control", "max-age=0");

If means that at the next request to the same URL the old response can not just be get from the server. The client have to re-validate the response. If you set no additional HTTP headers it means just get the request one more time. I recommend you to read the answer about the subject. By the way I personally use the above setting in the WCF always. In the case I use additionally prmNames: { nd:null} parameter. If you use datatype: 'local' instead of datatype: 'json' the setting do nothing.

Moreover another answer which I wrote today can be also interesting for you. It describes not the same, but very close scenario. It shows why it's not good to load the data from the server manually.

Community
  • 1
  • 1
Oleg
  • 220,925
  • 34
  • 403
  • 798
  • Hi Oleg. Thank you again! If I use Firefox, I don't run into the caching problem. In using IE, my default, I do have the caching problem. Firefox and IE both show the same data when I click the Reload Grid button. I did get the data: data.details to work BTW. I will try to get rid of the getJSON but I do that because of the class my data returns. It returns header data that I use to populate text boxes. I will look into that once I get some of these quirks knocked out. – DrZ Sep 17 '11 at 20:23
  • By adding this, $.ajaxSetup({ cache: false }); it seems to fix my IE caching issue. – DrZ Sep 17 '11 at 20:29
  • @DrZ: You are welcome! By the way if you would load the data by jqGrid you can define `jsonReader` so that you can read practically any JSON data. Moreover inside of `loadComplete` event handler you can see *any additional data from the server response*. The `loadComplete` has one parameter. It will be initialized to the full server data converted to the object: so exactly the same data which you has as `data` parameter of `success` handler of the `$.ajax`. – Oleg Sep 17 '11 at 20:33
  • @DrZ: II would recommend you to set `"Cache-Control: "max-age=0"` in the HTTP response of the server in any way. In the case you would be sure that *any* client will get always current data from the server. – Oleg Sep 17 '11 at 20:35
  • Write a book please :) I added the WebOperationContext statement to my web services and that does seem to do it. I can't thank you enough. – DrZ Sep 17 '11 at 20:47
  • Regarding the main topic of my question, do you think if I got rid of the JSON call and replaced it with the ajax call, that might address the issues with the Reload Grid problem? For example, if I edit a row, and then choose to display 10 records instead of 5, the old data is displayed. But the data is correct in the database. – DrZ Sep 17 '11 at 20:48
  • @DrZ: My last book I wrote more as 20 yeas before. It was about mathematics. To tell the truth I really think about writing of the book, and I will probably start soon with writing some articles (web pages). I should just find something time for it. Now back to your problem. It doesn't matter in which way you get the data. If you used HTTP GET the data *can be cached*. If you later get the data **from the same URL** the local cache of the web browser will be examined. The HTTP header information will be also saved (at least different caching options). The browser can decide where to get data. – Oleg Sep 17 '11 at 21:00
  • @DrZ: Everything si not so complex. I recommend you to read the [Caching Tutorial](http://www.mnot.net/cache_docs/) or read it from [here](http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html). You can read one more [my old answer](http://stackoverflow.com/questions/3704886/jqgrid-caching-the-grid-data/3722532#3722532) about the caching. – Oleg Sep 17 '11 at 21:03
0

setting cache: false in my ajax request solved the problem and I didn't have to reload the jqgrid each time. Thank you for asking this question and thank you to Oleg who has been a tremendous help on this site relating to the jqgrid.

vcuankit
  • 787
  • 2
  • 11
  • 12