具有远程过滤器和排序的ExtJS无限滚动网格

Aci*_*ier 17 javascript filtering extjs dom-events extjs4

在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,   
Run Code Online (Sandbox Code Playgroud)

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

store.prefetch({
    start: 0,
    limit: 200,
    callback: function() {
        store.guaranteeRange(0, 99);
    }
});   
Run Code Online (Sandbox Code Playgroud)

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

但是,如果我快速滚动或尝试使用过滤器激活无限滚动网格重新加载或在排序时它们全部分开.错误是options is undefined.

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

过滤正在崩溃,因为这种方法在Ext.data.Store无限卷轴需要来自服务器的更多数据时被无限卷轴调用:

mask: function() {
    this.masked = true;   
    this.fireEvent('beforeload');
},
Run Code Online (Sandbox Code Playgroud)

由于某种原因,此方法在没有参数的情况下触发beforeload事件,Ext.data.Operation参数应该是此处指定的参数.

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

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

},
Run Code Online (Sandbox Code Playgroud)

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

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

我想如果我能弄清楚如何用参数强制mask方法(就像文档说的那样),一切都会好的.问题是,我无法弄清楚如何做到这一点.有什么建议?beforeloadoperation

如果有人只是告诉我我错了,而且人们实际上已经做了这项工作,我会受到启发,但是你用来处理这个问题或链接的任何覆盖的片段都会非常感激.

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

更新 - 2月7日12:

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

Aci*_*ier 14

成功!我有无限滚动使用远程过滤器和远程排序(这是在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();
    }
});
Run Code Online (Sandbox Code Playgroud)

我的商店配置如下:

// 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
});
Run Code Online (Sandbox Code Playgroud)

网格是:

// 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...],
});
Run Code Online (Sandbox Code Playgroud)

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

store.prefetch({
    start: 0,
    limit: 200,
    callback: function() {
        store.guaranteeRange(0, 99);
    }
});    
Run Code Online (Sandbox Code Playgroud)