3

This question has been as a lot so please forgive me asking again.

I have a grid loaded from a url.

I use loadonce: true

I use filtertoolbar:

$("#status").jqGrid('filterToolbar', { stringResult:true, searchOnEnter:false, autosearch: true, defaultSearch: "cn" });

I have a dropdown search list from which I can select what I'm looking for. Works great.

I have a navbutton I click to initiate a reload every 30 seconds. Works great.

$("#status").jqGrid('navButtonAdd','#statuspager', { caption: '', buttonicon: 'ui-icon-play', onClickButton: function ()
{
stint = setInterval (function() {
      postfilt = $("#status").jqGrid('getGridParam', 'postData').filter;

      $("#status").jqGrid('setGridParam',{
             url: './ar_status.cgi?systemtype=' + systype,
             datatype: "json",
             postData: postfilt,
             search: true,
             loadtext: "Refreshing grid...",
             loadonce: true,
             loadui: "block"
      });
      $("#status").jqGrid().trigger("reloadGrid");
}, 30000);
},
title: 'Start Auto Refresh (every 30 sec.)'
});

Using google chrome I can see the filters that were specified being posted to the server:

systemtype:production
_search:true
nd:1358887757603
rows:1000
page:1
sidx:system
sord:asc
totalrows:700
filters:{"groupOp":"AND","rules":[{"field":"system","op":"eq","data":"ATTDA02"}]}

I can change the filter between reloads and see the new, even multiple filters:

systemtype:production
_search:true
nd:1358887847592
rows:1000
page:1
sidx:system
sord:asc
totalrows:700
filters:{"groupOp":"AND","rules":[{"field":"system","op":"eq","data":"ATTDA02"},{"field":"dow","op":"cn","data":"MO"}]}

I am using multipleSearch: true on the initial load. I'm pretty sure that's retained on reload

On the grid, the filtertoolbar retains my filter criteria, both text and selects, but when the grid reloads, the filters are ignored and the entire dataset is diplayed in the grid.

I've tried many examples posted here on SO. I've tried adding [{current:true}] to the reloadGrid call - no difference. I can't seem to retain and apply the filters on a reload.

I would like the reload to always return the full dataset from the server (which happens fine), and allow the current filter settings to control what is shown after the reload. I do not want to use the postdata to build a new SQL select statement - server side filtering, because at any time the user may want to click the pause button, select a new filter and view something else from the entire dataset without another reload.

$("#status").jqGrid('navButtonAdd','#statuspager', { caption: '', buttonicon: 'ui-icon-pause', onClickButton: function ()
{
   clearInterval(stint);
},
title: 'End Auto Refresh'
});

How can this be done without using cookies, as I saw in one post?

I could try using jqGridExport'ing the postfilt var, and then jqGridImport'ing it but was hoping for a more direct approach. I'm not even sure this would help since I already have everything I need right here in the grid via postData.

As a side note, in my setGridParam above, the loadtext I specify is never displayed. Instead, the default "Loading..." is displayed. All of the other parameters are working.

Many thanks in advance, Mike

Solution. The complete loadComplete to retain filters, sort index and sort order after a [json] reload from the server:

                    loadComplete: function() {
                            var $this = $(this);
                            postfilt = $this.jqGrid('getGridParam','postData').filters;
                            postsord = $this.jqGrid('getGridParam','postData').sord;
                            postsort = $this.jqGrid('getGridParam','postData').sidx;

                            if ($this.jqGrid("getGridParam", "datatype") === "json") {
                                    setTimeout(function () {
                                            $this.jqGrid("setGridParam", {
                                                    datatype: "local",
                                                    postData: {filters: postfilt, sord: postsord, sidx: postsort},
                                                    search: true
                                            });

                                            $this.trigger("reloadGrid");
                                    }, 50);
                            }
                    }
Mike
  • 59
  • 1
  • 1
  • 7

2 Answers2

4

Thanks very much!!!!

I only added a bit to your solution to retain the page number as well:

                loadComplete: function () {
                var $this = $(this);
                var postfilt = $this.jqGrid('getGridParam', 'postData').filters;
                var postsord = $this.jqGrid('getGridParam', 'postData').sord;
                var postsort = $this.jqGrid('getGridParam', 'postData').sidx;
                var postpage = $this.jqGrid('getGridParam', 'postData').page;

                if ($this.jqGrid("getGridParam", "datatype") === "json") {
                    setTimeout(function () {
                        $this.jqGrid("setGridParam", {
                            datatype: "local",
                            postData: { filters: postfilt, sord: postsord, sidx: postsort },
                            search: true
                        });
                        $this.trigger("reloadGrid", [{ page: postpage}]);
                    }, 25);
                }
            }
cmedine
  • 167
  • 1
  • 2
  • 11
2

I am not sure, but I suppose that the origin of your first problem could be mixing postData.filters and postData and usage filter property instead of filters``. You use

postfilt = $("#status").jqGrid('getGridParam', 'postData').filter;

to get filter property instead of filters. You get undefined value. So the setting postData to postfilt means nothing.

The next problem is that the server response contains non-filtered data. To force filtering the data locally you have to reload the grid once after the loading from the server have finished. You can do this inside of loadComplete. Exactly here you can set postData.filter if required, set search: true and trigger reloadGrid event. It's important only to do this once to have no recursion and you must don't set datatype back to "json" in the case. The datatype will be changed to "local" and the end of loading from the server in case of usage loadonce: true option. If you want apply filtering locally you have to reload grid once with options datatype: "local", search: true and postData having filters specifying the filter which need by applied. See the code from the answer or another one which do another things, but the code which you need will be very close.

Community
  • 1
  • 1
Oleg
  • 220,925
  • 34
  • 403
  • 798
  • Thanks for the guidance, Oleg. I still haven’t managed to make this work. I have to refresh the grid from the server each time and that means the datatype will be json each time. I’ve tried immediately setting the datatype to “local” but’ it’s not sticking, or the grid refreshes empty. I can follow the progress with a bunch of alert() calls and I can see it’s getting close; that datatype is being set to local, but even then the filters are not applied. I'll keep hacking at it. – Mike Jan 23 '13 at 23:45
  • @Mike: You are welcome! I can only repeat that you should follow the code from [the answer](http://stackoverflow.com/a/13679698/315935). You should load **full** data from the server having `datatype: "json"` and `loadonce: true`. Then you should trigger `reloadGrid` **immediately** from `loadCompleted` like in the answer. It make **local sorting and filtering applied** on the data loaded. Later you should change `datatype` to `"json"` when you need refresh the data by reloading it from the server. – Oleg Jan 24 '13 at 06:42
  • You are very patient, Oleg. I went over this again and [on purpose] I had left out the setTimeout function on loadComplete. It didn't seem necessary, but adding it back makes all the difference. I now have exactly what I'm after. I'm not big on copy/paste/hope it works. Can you explain why setTimeout is needed? – Mike Jan 24 '13 at 15:32
  • 1
    @Mike: The difference is **very large**. The callback function `loadComplete` will be called by jqGrid during processing of the data returned from the server (see [the line](https://github.com/tonytomov/jqGrid/blob/v4.4.3/js/grid.base.js#L1836)). So the processing of the response returned from the server is not finished. Usage of `setTimeout` allows to finish current processing of responses and *then* the next `reloadGrid` will be processed. – Oleg Jan 24 '13 at 15:49
  • I thought it might be something other than a delay mechanism because I can set the timeout to zero and still get the expected results. Anyway, thanks again for the help, and for all of your contributions to the jqgrid community. Very generous. – Mike Jan 24 '13 at 17:39
  • @Mike: It is delay mechanism. You can set breakpoint inside of `setTimeout` having 0 and you would see that the code inside of `setTimeout` will be executed **later**. If you examine source code of jqGrid you will find some places where `setTimeout` with 0 do used. – Oleg Jan 24 '13 at 17:54
  • @Mike: I recommend you remove `setTimeout` and repeat the same with setting breakpoint somewhere inside of `populete` function (for example [here](https://github.com/tonytomov/jqGrid/blob/v4.4.3/js/grid.base.js#L1814)) and you will see that code without `setTimeout` will process `populete` *at the second time* **before** the first call (inside of `loadComplete`) will be completed. – Oleg Jan 24 '13 at 17:55