I’m trying out ExtJs Ajax library and the first control I tried is the combo box. I tried out Jquery UI combo box, but it wasn’t working very well when filled with hundreds of values. It kept on resetting and reloading the page. It’s not a real component but a hack and is probably not meant to be used with so many values.
I then tried ExtJs combo box and it worked well with over a thousand choices in it. The power of a combo box versus a normal select box is that it makes it easy to find a value among several hundreds. If we have only a few choices there is no added value to have a combobox with tooltips.
However I wanted to modify the original behavior of Ext.form.ComboBox to allow to search anything in the middle of the record. In my particular case I had a ComboBox filled with customers, and that could be company names or surname and names. A company name could be “Romantic Furniture of John Pollock”, it can be as natural to type “Pol” because I can remember the surname and not the shop name. This behavior, as far as I could understand could not be achieved with the configuration parameters of extJS combobox. So I had to extend the class to redefine the doQuery method.
I got a little stucked with namespaces and I could not do a general extension, so it’s coded for the particular case. I hope to find a more general way soon, but so far my attempts have failed.
So basically in the Ext.onReady function I defined the following:
Ext.onReady(function() {
var store = new Ext.data.ArrayStore({
fields: ['id_person', 'descr'],
data: shopList
});
function AnyMatchCombo(config) {
AnyMatchCombo.superclass.constructor.call(this, config);
}
Ext.extend(AnyMatchCombo, Ext.form.ComboBox, {
minChars:2,
typeAhead: false,
mode: 'local',
triggerAction: 'all',
emptyText: 'Scrivi o Seleziona...', //translation
doQuery: function(q, forceAll) {
console.info('AnyMatchCombo '+q);
}
});
var combo = new AnyMatchCombo({
store: store,
valueField: 'id_person',
displayField: 'descr',
applyTo: 'searchCB'
});
});
Which basically works and calls my modified doQuery() function that for now just logs to the console. You need firebug to be open for the console to work. After testing it out, I can change the doQuery method with its actual implementation:
doQuery : function(q, forceAll){
q = Ext.isEmpty(q) ? '' : q;
var qe = {
query: q,
forceAll: forceAll,
combo: this,
cancel:false
};
if(this.fireEvent('beforequery', qe)===false || qe.cancel){
return false;
}
q = qe.query;
forceAll = qe.forceAll;
if(forceAll === true || (q.length >= this.minChars)){
if(this.lastQuery !== q){
this.lastQuery = q;
if(this.mode == 'local'){
this.selectedIndex = -1;
if(forceAll){
this.store.clearFilter();
}else{
this.store.filter(this.displayField, q);
}
this.onLoad();
}else{
this.store.baseParams[this.queryParam] = q;
this.store.load({
params: this.getParams(q)
});
this.expand();
}
}else{
this.selectedIndex = -1;
this.onLoad();
}
}
}
And after we’ve just to change line 22 as follows:
this.store.filter(this.displayField, q, true);