Javascript 带有远程过滤器和排序的ExtJS无限滚动网格
在ExtJS 4.1 beta 2中,我设法实现了一个带有远程存储的无限滚动网格。我基本上使用了一个现有的(完全可操作的)分页网格(带有远程存储、过滤和排序),然后将其放入适当的配置中进行无限滚动:Javascript 带有远程过滤器和排序的ExtJS无限滚动网格,javascript,extjs,extjs4,filtering,dom-events,Javascript,Extjs,Extjs4,Filtering,Dom Events,在ExtJS 4.1 beta 2中,我设法实现了一个带有远程存储的无限滚动网格。我基本上使用了一个现有的(完全可操作的)分页网格(带有远程存储、过滤和排序),然后将其放入适当的配置中进行无限滚动: // Use a PagingGridScroller (this is interchangeable with a PagingToolbar) verticalScrollerType: 'paginggridscroller', // do not reset the scrollbar w
// 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,
在中的任何地方都没有这样说(请参见无限滚动部分),但您需要将存储设置为具有缓冲区:true
配置。您不能使用store.load()
加载,它需要这样做:
store.prefetch({
start: 0,
limit: 200,
callback: function() {
store.guaranteeRange(0, 99);
}
});
有了这些,如果我慢慢滚动,允许数据预取,不使用任何过滤器,也不使用任何排序,那么一切都会很好
但是,如果我快速滚动,或者尝试在过滤器处于活动状态的情况下重新加载无限滚动网格,或者在对其进行排序时,所有这些都会断开。错误是选项未定义
我花了几个小时在代码和谷歌上做了一些跟踪,除了得出没有人使用远程过滤器和远程滚动实现无限滚动网格的结论之外,我发现了以下几点:
由于Ext.data.Store
中的此方法,过滤功能正在崩溃,当无限滚动程序需要从服务器获取更多数据时,会调用该方法:
mask: function() {
this.masked = true;
this.fireEvent('beforeload');
},
出于某种原因,此方法在不使用指定的Ext.data.Operation
参数的情况下触发beforeload
事件
因此,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请求
我没有深入讨论排序方面,但我认为它与这个掩码
方法类似,因为排序只是操作
对象包含的另一个元素,它会导致no操作对象被传递给ajax请求
我在想,如果我能用操作
参数(就像文档所说的那样)在加载之前强制mask
方法触发,一切都会好起来。问题是,我还不知道怎么做。有什么建议吗
如果有人告诉我,我错了,而且人们确实做了这项工作,我会受到启发,但如果您能提供一段用于处理此问题的覆盖或链接,我将不胜感激
我也尝试过降级到4.0.7和4.0.2a,我得到了相同的结果,所以这不仅仅是一个测试问题
更新-12年2月7日:
这似乎实际上可能是一个Ext.ux.grid.FilterFeature
问题,而不是无限滚动问题。如果我完全删除FilterFeature配置,无限滚动效果很好,并且在按列排序时将排序参数传递到后端。我将开始研究FilterFeature的最终目的。成功我使用远程过滤器和远程排序进行无限滚动(这是在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();
}
});
此外,初始加载必须像这样完成(不仅仅是store.load()):
你的回答提供了正确的方向,我从
store.loadRecords(Ext.Array.slice(records, 0, count));
到
这修复了以前的筛选器返回空结果的问题。插入此更改后,它工作正常。很好。我明白你的意思了,我想:当商店过滤到低于保证范围时,保证范围会保持在该范围内,不会加载更多。但您的解决方案的问题是,保证范围将变为与存储相同的大小,因此不会预取,这意味着当网格正常滚动时,一旦超过第200行或页面大小,它将永远不会重新加载。我在覆盖中添加了一个解决方案,它不是很动态。我将guaranteeRange变量设置为静态100,因为这就是我的变量。
// 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.prefetch({
start: 0,
limit: 200,
callback: function() {
store.guaranteeRange(0, 99);
}
});
store.loadRecords(Ext.Array.slice(records, 0, count));
store.loadRecords(Ext.Array.slice(records, 0, records.length));