PDA

View Full Version : TypeAhead for combobox with 'local' queryMode--cannot query for substring



JackJohnsonX
7 Jul 2015, 9:06 AM
Hello,

I'm using Ext 4.1.1

I have a combobox with typeAhead enabled for queryMode:"local". It works fine as long as you only query the prefix of the displayField. But nothing happens when you query for a substring in that display field.


{
xtype:"combo",
fieldLabel:"Country",
name:"COUNTRY",
itemId:"countryFilterFld",
labelPad:5,
typeAhead:true
queryMode:"local",
valueField:"ID",
displayField:"LABEL",
store:store
}

For Example, one of the LABEL's is "United States". If I start to type in "United", "United States" gets filtered. But if I type "States", nothing happens at all.

I also tried listening to the comboboxes "change" event then get the value and filter the combobox store but the change event does not even get fired.


listeners: {
change: function(cbo_) {
var store = cbo_.getStore();
store.clearFilter();
store.filter({
property: 'LABEL',
anyMatch: true,
value : cbo_.getValue()
})
}
},


I setup a breakpoint in the change event handler but the event is never fired, even after I am no longer focused on that field.

jdkhamba
8 Jul 2015, 3:49 AM
You could try something like this :

https://www.sencha.com/forum/showthread.php?156505-Local-combobox-with-any-match-filter.

But not sure whether it would work.

chamacs
8 Jul 2015, 10:26 AM
Ext 5.x has this built into it, but when we used Ext 4.1.1 we used the following override to enable this for comboboxes. When using this, remove the typeAhead:true and add anyMatch:true to the combobox configuration. (** typeAhead:true does conflict with this hence they are mutually exclusive with this override. The dropdown list is automatically filtered even without the typeAhead attribute).



// Override ComboBox.doQuery method, to allow for anyMatch local queries (enhancement to 4.1.1. Exists in 5.0.1)
Ext.override(Ext.form.field.ComboBox, {
// OVERRIDE (enhancement)
anyMatch : false,

doQuery: function(queryString, forceAll, rawQuery) {
queryString = queryString || '';


// store in object and pass by reference in 'beforequery'
// so that client code can modify values.
var me = this,
qe = {
query: queryString,
forceAll: forceAll,
combo: me,
cancel: false
},
store = me.store,
isLocalMode = me.queryMode === 'local',
needsRefresh;


if (me.fireEvent('beforequery', qe) === false || qe.cancel) {
return false;
}


// get back out possibly modified values
queryString = qe.query;
forceAll = qe.forceAll;


// query permitted to run
if (forceAll || (queryString.length >= me.minChars)) {
// expand before starting query so LoadMask can position itself correctly
me.expand();


// make sure they aren't querying the same thing
if (!me.queryCaching || me.lastQuery !== queryString) {
me.lastQuery = queryString;


if (isLocalMode) {
// forceAll means no filtering - show whole dataset.
store.suspendEvents();
needsRefresh = me.clearFilter();

// OVERRIDE - Because of conflicts with 'enhancement', do not allow anyMatch for typeAhead comboboxes
// ExtJS 5.0.1 has a complete solution
var anyMatchLocal = me.typeAhead ? false : me.anyMatch;

if (queryString || !forceAll) {
me.activeFilter = new Ext.util.Filter({
root: 'data',
property: me.displayField,
value: queryString
// OVERRIDE (enhancement)
, anyMatch : anyMatchLocal
});
store.filter(me.activeFilter);
needsRefresh = true;
} else {
delete me.activeFilter;
}
store.resumeEvents();
if (me.rendered && needsRefresh) {
me.getPicker().refresh();
}
} else {
// Set flag for onLoad handling to know how the Store was loaded
me.rawQuery = rawQuery;


// In queryMode: 'remote', we assume Store filters are added by the developer as remote filters,
// and these are automatically passed as params with every load call, so we do *not* call clearFilter.
if (me.pageSize) {
// if we're paging, we've changed the query so start at page 1.
me.loadPage(1);
} else {
store.load({
params: me.getParams(queryString)
});
}
}
}


// Clear current selection if it does not match the current value in the field
if (me.getRawValue() !== me.getDisplayValue()) {
me.ignoreSelection++;
me.picker.getSelectionModel().deselectAll();
me.ignoreSelection--;
}


if (isLocalMode) {
me.doAutoSelect();
}
if (me.typeAhead) {
me.doTypeAhead();
}
}
return true;
}
});


Example with override: https://fiddle.sencha.com/#fiddle/q3j

Hope this helps.

Gary Schlosberg
8 Jul 2015, 3:36 PM
Not sure how long until your next upgrade, but anyMatch was added in 4.2.1.
http://docs.sencha.com/extjs/4.2.1/#!/api/Ext.form.field.ComboBox-cfg-anyMatch

JackJohnsonX
15 Jul 2015, 9:22 AM
I ended up listening to the "keyup" event and then filtering the store. Like the "change" event, "keyup" was not being fired when configured directly inside combo.listeners obj for some reason unknown to me, but i was able to listen for it in the controller.


handleTypeAhead:function(cbo_){
cbo_.expand();
delete cbo_.lastQuery;
var store = cbo_.getStore();
store.clearFilter();
store.filter({
property: 'LABEL',
anyMatch: true,
value: cbo_.getValue()
});
}

anyMatch:true would have solved my problem yes, but I have yet to upgrade to 4.2x