【问题标题】:ExtJS Infinite Scroll Grid with remote Filters and Sort带有远程过滤器和排序的 ExtJS 无限滚动网格
【发布时间】:2012-02-27 17:12:47
【问题描述】:

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

// 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,   

docs 中的任何地方都没有这样说(请参阅无限滚动部分),但您需要将您的商店设置为具有 buffered: true 配置。而且你不能用store.load() 加载它需要这样做:

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

尽管如此,如果我慢慢滚动并允许数据预取,不使用任何过滤器,也不使用任何排序,一切都会很好。

但是,如果我快速滚动或尝试在激活过滤器的情况下重新加载无限滚动网格,或者在排序时,它会全部分解。错误是options is undefined

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

由于Ext.data.Store 中的这个方法,当它需要来自服务器的更多数据时,无限滚动器会调用该方法:

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

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

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

/**
 * @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);

},

我可以从 PagingScroller 代码中删除对 mask 方法的调用,然后滚动功能就很棒了。我可以随心所欲地滚动并正确加载数据。 但是然后过滤器和排序不会应用于 ajax 请求。

我没有深入研究排序方面,但我认为它与 mask 方法类似,因为 sort 只是 operation 对象包含的另一个元素,它会导致 no要传递给ajax请求的操作对象。

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

如果有人只是告诉我我错了并且人们实际上已经完成了这项工作,我会受到启发,但是非常感谢您用来处理此问题的任何覆盖或链接的 sn-p。

我也尝试过降级到 4.0.7 和 4.0.2a,我得到了相同的结果,所以这不仅仅是一个 beta 问题。

更新 - 12 年 2 月 7 日:

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

【问题讨论】:

    标签: javascript extjs extjs4 filtering dom-events


    【解决方案1】:

    您的回答提供了正确的方向,我从

    修改了您的代码
    store.loadRecords(Ext.Array.slice(records, 0, count));
    

    store.loadRecords(Ext.Array.slice(records, 0, records.length));
    

    这解决了您之前的过滤器返回空结果的问题。在我插入此更改后,它工作正常。

    【讨论】:

    • 好地方。我明白你在说什么,我认为:当商店过滤到低于保证范围时,保证范围会保持在那个数量并且不会加载更多。但是,您的解决方案的问题是保证范围将变得与商店的大小相同,因此不会预取,这意味着当网格正常滚动时,一旦您超过第 200 行或其他任何内容,它将永远不会重新加载页面大小是。我在覆盖中添加了一个解决方案,它不是很动态。我设置的保证范围变量为静态 100,因为这就是我的。
    【解决方案2】:

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

    我还没有在其他浏览器中进行过测试,但我已经在 FF 中进行了测试。以下是我正在使用的覆盖:

    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()):

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-10-06
      • 1970-01-01
      • 2012-04-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多