Ron
Ron

Reputation: 1336

ExtJS: Reload datastore without redrawing grid

(ExtJS 3.3.1)

How can I save the scroll position of a grid after I call grid.store.reload()?

Upvotes: 5

Views: 8387

Answers (5)

Craig Holzinger
Craig Holzinger

Reputation: 1

This post recently helped me find that the view maintains the control over the scrollState. I was able to view.saveScrollState() then defer view.restoreScrollState() with a timeOut. The longer the timeout the more jarring the return is, so be aware that you want the minimum amount of timeOut for the view to refresh / render. What was missing from earlier posts was that the view has a "saveScrollState" where it stores scroll position internally.

view.saveScrollState();
//do some things here
setTimeout(function(){
   view.restoreScrollState();
},1);

Upvotes: 0

Naresh
Naresh

Reputation: 1

listeners: {
                beforerefresh: function(v) {
                    v.hide();
                },
                refresh: function(v) {
                    v.show();
                }
            }

worked for me (add in view config)

Upvotes: 0

Paul Mestrum
Paul Mestrum

Reputation: 66

I managed to fix it like this:

this.store = new Ext.data.Store({
    listeners:{
        'load':function (store, records, options) {
            var restoreScroll = function(scrollState){
                grid.getView().restoreScroll(scrollState);
            };
            if (grid.view && grid.view.scroller){
                _.delay(restoreScroll, 10,grid.getView().getScrollState());
            }
        }
    }, ...
}

As you can see, I use _.delay (of the underscore.js framework). It's just like a setTimeout.

A more optimized version, not using the the function 'restoreScroll' didn't work out. I think that the view is changed when restoreScroll is called. I had to take 10 miliseconds. 1 was not enough. As stated by others, ext.js uses a lot of defer-calls.

Upvotes: 5

Ron
Ron

Reputation: 1336

Finally I found this section in the extjs grid faq. This snipped does not directly run in webkit-browsers. You have to add a timeout and call the restore part a little moment later. 100ms helped me out here. This is what I have now:

grid.getView().on('beforerefresh', function(view) {
  view.scrollTop = view.scroller.dom.scrollTop;
  view.scrollHeight = view.scroller.dom.scrollHeight;
});

grid.getView().on('refresh', function(view) {
    setTimeout(function () {
        view.scroller.dom.scrollTop = view.scrollTop + (view.scrollTop == 0 ? 0 : view.scroller.dom.scrollHeight - view.scrollHeight);
    }, 100);
});

Runs in IE8, Chrome9, Firefox3.6

Does not in Opera 11

This solution has one drawback: Without activly telling the view not to restore the scroll position it is also restored if you goto next page by the paginator.

I think sencha should integrate this feature as a option, because it is a deep integration to tell the view of a grid to restore the position if a store reloads the same position of a datasource and not to do so if changes to the baseparams are made... or so.

Upvotes: 4

user123444555621
user123444555621

Reputation: 152986

That's two different questions.

First, to reload a store without redrawing the grid, use store.suspendEvents(), then call store.resumeEvents() in the load callback.

Restoring scroll position after refresh is a bit more tricky, particularly since ExtJS makes excessive use of setTimeouts and defers in Firefox. Try saving the scroll state using var state = view.getScrollState(), then restore it with view.restoreScroll.defer(1, state)

Upvotes: 4

Related Questions