具有远程过滤器和排序功能的ExtJS无限滚动网格 [英] ExtJS Infinite Scroll Grid with remote Filters and Sort

查看:84
本文介绍了具有远程过滤器和排序功能的ExtJS无限滚动网格的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在ExtJS 4.1 beta 2中,我设法通过远程存储实现了无限滚动网格。我基本上采用了一个现有的(完全可操作的)分页网格(带有远程存储,过滤和排序功能),然后放入适当的配置以进行无限滚动:

In ExtJS 4.1 beta 2 I managed to implement an infinite scroll grid with a remote store. I basically took an existing (fully operational) paging grid (with remote store, filtering and sorting) and then put in the appropriate configs for infinite scrolling:

// Use a PagingGridScroller (this is interchangeable with a PagingToolbar)
verticalScrollerType: 'paginggridscroller',
// do not reset the scrollbar when the view refreshs
invalidateScrollerOnRefresh: false,
// infinite scrolling does not support selection
disableSelection: true,   

文档(请参阅无限滚动部分),但是您需要将商店设置为具有 buffered:true 配置。而且您无法使用 store.load()进行加载,需要这样做:

It doesn't say this anywhere in the docs(see Infinite Scrolling section), but you need to set your store to have buffered: true config. And you can't load with store.load() it needs to be done like this:

store.prefetch({
    start: 0,
    limit: 200,
    callback: function() {
        store.guaranteeRange(0, 99);
    }
});   

所有这些,如果我缓慢滚动从而允许数据预取,一切都会很好用,不要

With all that, everything works great if I scroll slowly and thus allow the data to prefetch, don't use any filters and don't use any sorting.

但是,如果我快速滚动或尝试在激活过滤器时或在对其进行排序时尝试使无限滚动网格重新加载,请不要使用任何过滤器一切都破裂了。错误是选项未定义

However, if I scroll fast or try to make the infinite scroll grid reload with a filter active or while sorting it all breaks apart. Error is options is undefined.

我花了几个小时在代码中进行了一些跟踪和谷歌搜索除了得出结论,没有人使用远程过滤器和远程滚动实现无限滚动网格外,我发现以下内容:

I've spent a couple of hours doing some tracing in the code and googling and aside from concluding that no one has implemented an infinite scroll grid with remote filters and remote scrolling, I have found the following:

由于这种方法,过滤器崩溃了在 Ext.data.Store 中,当无限滚动条需要从服务器获取更多数据时,它将被调用:

The filtering is breaking down because of this method in Ext.data.Store which is called by the infinite scroller when it needs more data from the server:

mask: function() {
    this.masked = true;   
    this.fireEvent('beforeload');
},

由于某种原因,此方法会触发 beforeload 事件没有 Ext.data.Operation 参数,该参数应该是指定的一部分此处

For some reason, this method fires the beforeload event without the Ext.data.Operation parameter which is supposed to be part of it as specified here.

结果,在 Ext.ux.grid.FiltersFeature onbeforeload 处理程序中发生错误>因为选项当然是未定义的:

As a result, an error occurs in the onbeforeload handler in Ext.ux.grid.FiltersFeature because of course "options" is undefined:

/**
 * @private
 * Handler for store's beforeload event when configured for remote filtering
 * @param {Object} store
 * @param {Object} options
 */
onBeforeLoad : function (store, options) {

    options.params = options.params || {};
    this.cleanParams(options.params);
    var params = this.buildQuery(this.getFilterData());
    Ext.apply(options.params, params);

},

我可以切断对此<$ c的呼叫PagingScroller代码中的$ c> mask 方法,然后滚动功能很棒。我可以根据需要快速滚动,并且可以正确加载数据。 但是然后过滤器和排序不会应用于ajax请求。

I can cut out the call to this mask method from the PagingScroller code and then the scroll functionality is great. I can scroll as fast as I like and it loads the data properly. But then filters and sort does not get applied to the ajax requests.

我在排序方面的投入还不多,但我认为与此 mask 方法类似,因为sort只是操作对象包含的另一个元素,它会导致没有操作对象传递给ajax请求。

I haven't dived as much into the sorting aspect but I think it something similar with this mask method because sort is simply another element contained by the operation object and it causes no operation object to be passed to the ajax request.

我在想,如果我能弄清楚如何强制 mask 方法使用 operation 参数触发 beforeload (就像文档说的那样)应该)一切都会好的。问题是,我还无法弄清楚该怎么做。有什么建议吗?

I'm thinking that if I could just figure out how to force the mask method to fire beforeload with the operation parameter (like the docs say it is supposed to) everything will be fine. Problem is, I haven't been able to figure out how to do that. Any suggestions?

如果有人只是告诉我我错了,而实际上人们已经做了这项工作,那我会很受启发,但是您使用的任何替代代码段处理这个问题或链接将不胜感激。

If someone would just tell me that I am wrong and people have in fact made this work, I would be inspired, but a snippet of any overrides you used to handle this problem or a link would be much appreciated.

我还尝试将其降级到4.0.7和4.0.2a,并且得到相同的结果,所以它不仅仅是测试版问题。

I've also tried downgrading to 4.0.7 and 4.0.2a and I get the same results, so it isn't just a beta problem.

更新-2012年2月7日:

这似乎实际上是一个 Ext.ux.grid.FilterFeature 问题,而不是无限滚动的问题。如果我删除FilterFeature配置,则无限滚动效果很好,并且在按列排序时确实会将排序参数传递给我的后端。我将开始研究FilterFeature的结尾。

This seems like it may actually be a Ext.ux.grid.FilterFeature problem not an infinite scrolling problem. If I remove the FilterFeature config entirely infinite scrolling works great and does pass the sorting params to my backend when I sort by a column. I will start looking into the FilterFeature end of things.

推荐答案

成功!我可以无限滚动工作使用远程过滤器和远程排序(这是4.1 beta 2中的版本,但是因为我在4.02a和4.0.7中遇到了相同的错误,所以我想它也可以解决这些错误)。基本上,我只需要在代码中添加一些替代。

SUCCESS! I have infinite scrolling working with a remote filter and remote sort (this is in 4.1 beta 2, but because I was getting the same errors in 4.02a and 4.0.7 I imagine that it would resolve those too). Basically, I just had to add a few overrides in my code.

我还没有在其他浏览器中进行过测试,但是我已经在FF中进行了测试。这是我使用的替代项:

I haven't done testing in other browsers but I have it going in FF. Here are the overrides that I am using:

Ext.override(Ext.data.Store, {

    // Handle prefetch when all the data is there and add purging
    prefetchPage: function(page, options, forceLoad) {

        var me = this,
            pageSize = me.pageSize || 25,
            start = (page - 1) * me.pageSize,
            end = start + pageSize;

        // A good time to remove records greater than cache
        me.purgeRecords();

        // No more data to prefetch
        if (me.getCount() === me.getTotalCount() && !forceLoad) {
            return;
        }

        // Currently not requesting this page and range isn't already satisified
        if (Ext.Array.indexOf(me.pagesRequested, page) === -1 && !me.rangeSatisfied(start, end)) {
            me.pagesRequested.push(page);

            // Copy options into a new object so as not to mutate passed in objects
            options = Ext.apply({
                page     : page,
                start    : start,
                limit    : pageSize,
                callback : me.onWaitForGuarantee,
                scope    : me
            }, options);
            me.prefetch(options);
        }
    },

    // Fixes too big guaranteedEnd and forces load even if all data is there
    doSort: function() {
        var me = this;
        if (me.buffered) {
            me.prefetchData.clear();
            me.prefetchPage(1, {
                callback: function(records, operation, success) {
                    if (success) {
                        guaranteeRange = records.length < 100 ? records.length : 100
                        me.guaranteedStart = 0;
                        me.guaranteedEnd = 99; // should be more dynamic
                        me.loadRecords(Ext.Array.slice(records, 0, guaranteeRange));
                        me.unmask();
                    }
                }
            }, true);
            me.mask();
        }
    }
});   

Ext.override(Ext.ux.grid.FiltersFeature, {

    onBeforeLoad: Ext.emptyFn,

    // Appends the filter params, fixes too big guaranteedEnd and forces load even if all data is there
    reload: function() {
        var me = this,
            grid = me.getGridPanel(),
            filters = grid.filters.getFilterData(),
            store = me.view.getStore(),
            proxy = store.getProxy();

        store.prefetchData.clear();
        proxy.extraParams = this.buildQuery(filters);
        store.prefetchPage(1, {
            callback: function(records, operation, success) {
                if (success) {
                        guaranteeRange = records.length < 100 ? records.length : 100;
                        store.guaranteedStart = 0;
                        store.guaranteedEnd = 99; // should be more dynamic
                        store.loadRecords(Ext.Array.slice(records, 0, guaranteeRange));
                    store.unmask();
                }
            } 
        }, true);
        store.mask();
    }
});

我的商店配置如下:

// the paged store of account data
var store = Ext.create('Ext.data.Store', {
    model: 'Account',
    remoteSort: true,
    buffered: true,
    proxy: {
        type: 'ajax', 
        url: '../list?name=accounts', //<-- supports remote filter and remote sort
        simpleSortMode: true,
        reader: {
            type: 'json',
            root: 'rows',
            totalProperty: 'total'
        }
    },
    pageSize: 200
});

网格为:

// the infinite scroll grid with filters
var grid = Ext.create('Ext.grid.Panel', {
    store: store,
    viewConfig: {
        trackOver: false,
        singleSelect: true,
    },
    features: [{
        ftype: 'filters',
        updateBuffer: 1000 // trigger load after a 1 second timer
    }],
    verticalScrollerType: 'paginggridscroller',
    invalidateScrollerOnRefresh: false,         
    // grid columns
    columns: [columns...],
});

此外,初始加载必须像这样完成(不仅仅是store.load()):

Also the initial load must be done like this (not just store.load()):

store.prefetch({
    start: 0,
    limit: 200,
    callback: function() {
        store.guaranteeRange(0, 99);
    }
});    

这篇关于具有远程过滤器和排序功能的ExtJS无限滚动网格的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆