Using Ext JS 7.1 Modern, I have prepared an example to show the problem.
When I have remote filters on my main store, binding the dataview.List
to a ChainedStore
correctly handles my local filtering. However, when I also add a PullRefresh
plugin to the list, I get an error during pull refresh. I see from the source code that the plugin doesn't consider the possibility that a list's store can be a ChainedStore
.
I have tried to explain the problem with a Sencha Fiddle and also attached the code below.
I have temporarily solved the problem by overriding the fetchLatest
and onLatestFetched
methods of Ext.dataview.pullrefresh.PullRefresh
plugin, to use the source
store if the list's store is a ChainedStore
. But I believe the source code must be updated to handle this case.
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);
}
}
}
})
Thanks in advance
Since this post, instead of being a question, was a bug report with a possible solution, it has been posted to Ext JS 7.x Community Forums\Ext JS 7.x Bugs.
The above solution, that overwrites the plugin where source store is needed, works if anyone comes across the same issue.