我已经在Sencha论坛上发布了这篇文章,也想在这里发布,以防万一:
我有一个GridPanel,它使用了一个分页工具栏和一个复选框选择模型。我想跨页面跟踪所选内容。我快到了,但我遇到了PagingToolbar控件(如下一页)在我的选择模型上触发"selectionchange"事件的问题。
以下是我的代码的简化示例:
代码:
var sm = Ext.create('Ext.selection.CheckboxModel', {
listeners:{
selectionchange: function(selectionModel, selectedRecords, options){
console.log("Selection Change!!");
// CODE HERE TO KEEP TRACK OF SELECTIONS/DESELECTIONS
}
}
});
var grid = Ext.create('Ext.grid.Panel', {
autoScroll:true,
store: store,
defaults: {
sortable:true
},
selModel: sm,
dockedItems: [{
xtype: 'pagingtoolbar',
store: store,
dock: 'bottom',
displayInfo: true
}],
listeners: {'beforerender' : {fn:function(){
store.load({params:params});
}}}
});
store.on('load', function() {
console.log('loading');
console.log(params);
console.log('selecting...');
var records = this.getNewRecords();
var recordsToSelect = getRecordsToSelect(records);
sm.select(recordsToSelect, true, true);
});
我假设我可以选择加载事件上的记录,而不触发任何事件。
这里发生的情况是,selectionchange事件是在更改数据页时触发的,我不希望发生这种情况。理想情况下,只有用户点击会被跟踪为"selectionchange"事件,而不是任何其他组件的事件在我的选择模型上冒泡并触发事件。查看源代码,我能看到在PagingToolbar上触发的唯一事件是"change"。我试图了解GridPanel、TablePanel、Gridview等是如何处理的,但我只是看不到事件的路径。即便如此,我也不知道如何将事件从PagingToolbar抑制到SelectionModel。
提前感谢,Tom
我已经处理好了。关键是检测页面的更改位置。最简单的解决方案是为选择侦听器设置缓冲区并检查Store.loading
属性。以下是我选择模型的实现:
var selModel = Ext.create('Ext.selection.CheckboxModel', {
multipageSelection: {},
listeners:{
selectionchange: function(selectionModel, selectedRecords, options){
// do not change selection on page change
if (selectedRecords.length == 0 && this.store.loading == true && this.store.currentPage != this.page) {
return;
}
// remove selection on refresh
if (this.store.loading == true) {
this.multipageSelection = {};
return;
}
// remove old selection from this page
this.store.data.each(function(i) {
delete this.multipageSelection[i.id];
}, this);
// select records
Ext.each(selectedRecords, function(i) {
this.multipageSelection[i.id] = true;
}, this);
},
buffer: 5
},
restoreSelection: function() {
this.store.data.each(function(i) {
if (this.multipageSelection[i.id] == true) {
this.select(i, true, true);
}
}, this);
this.page = this.store.currentPage;
}
并且需要额外的绑定来存储:
store.on('load', grid.getSelectionModel().restoreSelection, grid.getSelectionModel());
工作样品:http://jsfiddle.net/pqVmb/
Lolo的解决方案很棒,但它似乎不再适用于ExtJS 4.2.1。
使用以下内容代替"selectionchange":
deselect: function( selectionModel, record, index, eOpts ) {
delete this.multipageSelection[i.id];
},
select: function( selectionModel, record, index, eOpts ) {
this.multipageSelection[i.id] = true;
},
这是ExtJs5的一个解决方案,利用MVVC在视图模型中创建一个名为"selectedObjects"的本地存储,其模型与分页网格相同。
在checkboxmodel上添加选择和取消选择侦听器。在这些功能中,添加或删除本地存储中选定或取消选定的记录。
onCheckboxModelSelect: function(rowmodel, record, index, eOpts) {
// Add selected record to the view model store
this.getViewModel().getStore('selectedObjects').add(record);
},
onCheckboxModelDeselect: function(rowmodel, record, index, eOpts) {
// Remove selected record from the view model store
this.getViewModel().getStore('selectedObjects').remove(record);
},
在页面工具栏上,添加一个更改侦听器,以便在出现在页面中时重新选择以前选择的记录。
onPagingtoolbarChange: function(pagingtoolbar, pageData, eOpts) {
// Select any records on the page that have been previously selected
var checkboxSelectionModel = this.lookupReference('grid').getSelectionModel(),
selectedObjects = this.getViewModel().getStore('selectedObjects').getRange();
// true, true params. keepselections if any and suppresses select event. Don't want infinite loop listeners.
checkboxSelectionModel.select(selectedObjects, true, true);
},
在完成任何操作之后,不再需要这些选择。在checkboxmodel上调用deselectAll,如果它不是已销毁的视图,则从本地存储中移除All。(Windows关闭时,它们默认设置为调用destroy,并负责本地存储数据清理,如果是这样的话)