列表的 PullRefresh 插件不处理 ChainedStore 的可能性
PullRefresh plugin of a List doesn't handle ChainedStore possibility
使用 Ext JS 7.1 Modern,我准备了一个例子来说明问题。
当我的主存储上有远程过滤器时,将 dataview.List
绑定到 ChainedStore
可以正确处理我的本地过滤。但是,当我还向列表中添加 PullRefresh
插件时,在拉动刷新期间出现错误。我从源代码中看到插件没有考虑列表存储可以是 ChainedStore
.
的可能性
我已经尝试用 Sencha Fiddle 来解释问题,并附上了下面的代码。
我通过重写 Ext.dataview.pullrefresh.PullRefresh
插件的 fetchLatest
和 onLatestFetched
方法暂时解决了这个问题,如果列表的存储是 ChainedStore
。但我认为必须更新源代码才能处理这种情况。
app.js
Ext.define('App.model.Test', {
extend: 'Ext.data.Model',
fields: ['id', 'firstName', 'lastName']
});
Ext.define('App.store.Test', {
extend: 'Ext.data.Store',
alias: 'store.teststore',
model: 'App.model.Test'
});
Ext.define('App.viewmodel.Test', {
extend: 'Ext.app.ViewModel',
alias: 'viewmodel.test',
data: {
query: ''
},
stores: {
test: {
type: 'teststore',
autoLoad: true,
proxy: {
type: 'ajax',
url: 'names.json',
reader: {
type: 'json',
rootProperty: 'data'
}
},
remoteFilter: true,
filters: {
property: 'id',
value: 1
}
},
chained: {
type: 'chained',
autoLoad: true,
source: '{test}'
}
}
});
Ext.define('App.controller.TestController', {
extend: 'Ext.app.ViewController',
alias: 'controller.testcontroller',
doSearch: function (field) {
var list = this.lookup('list'),
store = list.getStore(),
value = field.getValue();
if (Ext.isEmpty(value)) {
store.removeFilter('firstName')
} else {
store.filter([{
property: 'firstName',
value: value,
operator: 'like'
}])
}
}
});
Ext.define('App.dataview.TestList', {
extend: 'Ext.dataview.List',
xtype: 'testlist',
viewModel: {
type: 'test'
},
plugins: [{
type: 'pullrefresh',
mergeData: false
}],
emptyText: 'Name not found',
bind: {
store: '{chained}'
},
itemTpl: '<div class="contact">{id} <b>{firstName} {lastName}</b></div>'
});
Ext.define('App.MainView', {
extend: 'Ext.Panel',
controller: 'testcontroller',
fullscreen: true,
viewModel: {
type: 'test'
},
items: [{
xtype: 'searchfield',
ui: 'solo',
placeholder: 'Search names',
listeners: {
buffer: 500,
change: 'doSearch'
},
bind: {
value: '{query}'
}
}, {
reference: 'list',
xtype: 'testlist'
}]
})
Ext.application({
name: 'App',
mainView: 'App.MainView'
});
names.json
var data = [{
id: 1,
firstName: 'Peter',
lastName: 'Venkman'
}, {
id: 2,
firstName: 'Raymond',
lastName: 'Stantz'
}, {
id: 3,
firstName: 'Egon',
lastName: 'Spengler'
}, {
id: 4,
firstName: 'Winston',
lastName: 'Zeddemore'
}]
var results = data.filter(function(record) {
if (params.filter) {
return record.id > params.filter[0].value
}
})
return {
"success": true,
"data": results
}
App.override.dataview.pullrefresh.PullRefresh:
Ext.define('App.override.dataview.pullrefresh.PullRefresh', {
override: 'Ext.dataview.pullrefresh.PullRefresh',
privates: {
fetchLatest: function() {
const store = this.getStore().isChainedStore ? this.getStore().getSource() : this.getStore()
store.fetch({
page: 1,
start: 0,
callback: this.onLatestFetched,
scope: this
});
},
onLatestFetched: function(newRecords, operation, success) {
var me = this,
list = me.getList(),
store = list.getStore().isChainedStore ? list.getStore().getSource() : list.getStore(),
length, toInsert,
oldRecords, newRecord, oldRecord, i;
if (success) {
if (me.getMergeData()) {
oldRecords = store.getData();
toInsert = [];
length = newRecords.length;
for (i = 0; i < length; i++) {
newRecord = newRecords[i];
oldRecord = oldRecords.getByKey(newRecord.getId());
if (oldRecord) {
oldRecord.set(newRecord.getData());
}
else {
toInsert.push(newRecord);
}
}
store.insert(0, toInsert);
}
else {
store.loadRecords(newRecords);
}
me.setLastUpdated(new Date());
}
me.setState('loaded');
list.fireEvent('latestfetched', me, toInsert || newRecords);
if (me.getAutoSnapBack()) {
me.snapBack(true);
}
}
}
})
提前致谢
由于此 post 不是一个问题,而是一个带有可能解决方案的错误报告,因此它已被 post 编辑到 Ext JS 7.x Community Forums\Ext JS 7.x Bugs。
上面的解决方案覆盖了需要源存储的插件,如果有人遇到同样的问题,它是有效的。
使用 Ext JS 7.1 Modern,我准备了一个例子来说明问题。
当我的主存储上有远程过滤器时,将 dataview.List
绑定到 ChainedStore
可以正确处理我的本地过滤。但是,当我还向列表中添加 PullRefresh
插件时,在拉动刷新期间出现错误。我从源代码中看到插件没有考虑列表存储可以是 ChainedStore
.
我已经尝试用 Sencha Fiddle 来解释问题,并附上了下面的代码。
我通过重写 Ext.dataview.pullrefresh.PullRefresh
插件的 fetchLatest
和 onLatestFetched
方法暂时解决了这个问题,如果列表的存储是 ChainedStore
。但我认为必须更新源代码才能处理这种情况。
app.js
Ext.define('App.model.Test', {
extend: 'Ext.data.Model',
fields: ['id', 'firstName', 'lastName']
});
Ext.define('App.store.Test', {
extend: 'Ext.data.Store',
alias: 'store.teststore',
model: 'App.model.Test'
});
Ext.define('App.viewmodel.Test', {
extend: 'Ext.app.ViewModel',
alias: 'viewmodel.test',
data: {
query: ''
},
stores: {
test: {
type: 'teststore',
autoLoad: true,
proxy: {
type: 'ajax',
url: 'names.json',
reader: {
type: 'json',
rootProperty: 'data'
}
},
remoteFilter: true,
filters: {
property: 'id',
value: 1
}
},
chained: {
type: 'chained',
autoLoad: true,
source: '{test}'
}
}
});
Ext.define('App.controller.TestController', {
extend: 'Ext.app.ViewController',
alias: 'controller.testcontroller',
doSearch: function (field) {
var list = this.lookup('list'),
store = list.getStore(),
value = field.getValue();
if (Ext.isEmpty(value)) {
store.removeFilter('firstName')
} else {
store.filter([{
property: 'firstName',
value: value,
operator: 'like'
}])
}
}
});
Ext.define('App.dataview.TestList', {
extend: 'Ext.dataview.List',
xtype: 'testlist',
viewModel: {
type: 'test'
},
plugins: [{
type: 'pullrefresh',
mergeData: false
}],
emptyText: 'Name not found',
bind: {
store: '{chained}'
},
itemTpl: '<div class="contact">{id} <b>{firstName} {lastName}</b></div>'
});
Ext.define('App.MainView', {
extend: 'Ext.Panel',
controller: 'testcontroller',
fullscreen: true,
viewModel: {
type: 'test'
},
items: [{
xtype: 'searchfield',
ui: 'solo',
placeholder: 'Search names',
listeners: {
buffer: 500,
change: 'doSearch'
},
bind: {
value: '{query}'
}
}, {
reference: 'list',
xtype: 'testlist'
}]
})
Ext.application({
name: 'App',
mainView: 'App.MainView'
});
names.json
var data = [{
id: 1,
firstName: 'Peter',
lastName: 'Venkman'
}, {
id: 2,
firstName: 'Raymond',
lastName: 'Stantz'
}, {
id: 3,
firstName: 'Egon',
lastName: 'Spengler'
}, {
id: 4,
firstName: 'Winston',
lastName: 'Zeddemore'
}]
var results = data.filter(function(record) {
if (params.filter) {
return record.id > params.filter[0].value
}
})
return {
"success": true,
"data": results
}
App.override.dataview.pullrefresh.PullRefresh:
Ext.define('App.override.dataview.pullrefresh.PullRefresh', {
override: 'Ext.dataview.pullrefresh.PullRefresh',
privates: {
fetchLatest: function() {
const store = this.getStore().isChainedStore ? this.getStore().getSource() : this.getStore()
store.fetch({
page: 1,
start: 0,
callback: this.onLatestFetched,
scope: this
});
},
onLatestFetched: function(newRecords, operation, success) {
var me = this,
list = me.getList(),
store = list.getStore().isChainedStore ? list.getStore().getSource() : list.getStore(),
length, toInsert,
oldRecords, newRecord, oldRecord, i;
if (success) {
if (me.getMergeData()) {
oldRecords = store.getData();
toInsert = [];
length = newRecords.length;
for (i = 0; i < length; i++) {
newRecord = newRecords[i];
oldRecord = oldRecords.getByKey(newRecord.getId());
if (oldRecord) {
oldRecord.set(newRecord.getData());
}
else {
toInsert.push(newRecord);
}
}
store.insert(0, toInsert);
}
else {
store.loadRecords(newRecords);
}
me.setLastUpdated(new Date());
}
me.setState('loaded');
list.fireEvent('latestfetched', me, toInsert || newRecords);
if (me.getAutoSnapBack()) {
me.snapBack(true);
}
}
}
})
提前致谢
由于此 post 不是一个问题,而是一个带有可能解决方案的错误报告,因此它已被 post 编辑到 Ext JS 7.x Community Forums\Ext JS 7.x Bugs。
上面的解决方案覆盖了需要源存储的插件,如果有人遇到同样的问题,它是有效的。