PDA

View Full Version : [1.1.1] Local ComboBox data store filter not cleared on call to setValue()



wck555
7 Nov 2007, 5:59 AM
If you setup a ComboBox like this:


combo = new Ext.form.ComboBox({
fieldLabel: 'Class',
hiddenName: 'MEClassID', // name of field bound to this control
displayField: 'text',
valueField: 'id',
width:100,
mode:'local',
typeAhead:true,
triggerAction:'all',
selectOnFocus: true,
forceSelection: true,
store: new Ext.data.SimpleStore({ fields: ['id', 'text'], data: meClassLookup })
}));
you get a ComboBox that displays 'text' values to the user while storing 'id' values behind the scenes. If you call setValue(id), the ComboBox displays the 'text' value from the data store associated with that 'id'. If the user types into the ComboBox, the data store items are filtered to match what the user is typing and displayed to the user in a pop-down list. When the user chooses an item, the 'text' value is displayed and the 'id' value is stored. Cool :)

The problem arises if you call setValue() (or load form data or do anything else that causes Ext to call setValue() behind the scenes) after the user has selected an item in the ComboBox by typing. The filter applied to the data store while the user was typing still remains. When setValue() is called, the ComboBox searches the data store looking for a matching 'id' and then displays the associated 'text' value. However the data store is still filtered. So if the 'text' value associated with the new 'id' doesn't match the filter (i.e. doesn't match what the user typed into the ComboBox), the ComboBox will fail to find the 'text' value to match the new 'id' and will fallback to displaying the 'id' value instead.

There is a fairly straightforward workaround for now. You have to subclass the ComboBox class like this (I also added a few default values to match my needs, but these are optional)


Ext.form.LocalComboBox = Ext.extend(Ext.form.ComboBox, {
mode:'local',
typeAhead:true,
triggerAction:'all',
selectOnFocus: true,
forceSelection: false,
setValue: function(v)
{
// --- When user types a value into a combobox Ext creates a filter on the
// --- data store attached to the combobox to filter the values displayed to the user.
// --- Later, if setValue() is called, this filter is still set in the data store and
// --- the combo box may not display the text associated with the value.
// --- To work around this, clear the data store filter
this.store.clearFilter();
// --- Then call base class setValue() function
Ext.form.LocalComboBox.superclass.setValue.call(this, v);
}
});
Then use LocalComboBox whenever you need a ComboBox with a local data store

combo = new Ext.form.LocalComboBox({
fieldLabel: 'Class',
hiddenName: 'MEClassID', // name of field bound to this control
displayField: 'text',
valueField: 'id',
width:100,
forceSelection: true,
store: new Ext.data.SimpleStore({ fields: ['id', 'text'], data: meClassLookup })
}));

LoneTiger
8 Nov 2007, 3:13 AM
Thanks for sharing. Was having the exact same problem but using a regular data store.

wck555
8 Nov 2007, 8:27 AM
There is a problem with my workaround and typeAhead. If typeAhead=true and the user types very quickly and presses <Enter> before the typeAhead delay, the first item in the data store will be selected, not the first item that matches what the user typed. Unfortunately the only fix I have for this is to disable typeAhead by default

Ext.form.LocalComboBox = Ext.extend(Ext.form.ComboBox, {
mode:'local',
typeAhead:false, // must be false to prevent wrong item being selected when user types quickly
triggerAction:'all',
selectOnFocus: true,
forceSelection: false,
setValue: function(v)
{
// --- When user types a value into a combobox Ext creates a filter on the
// --- data store attached to the combobox to filter the values displayed to the user.
// --- Later, if setValue() is called, this filter is still set in the data store and
// --- the combo box may not display the text associated with the value.
// --- To work around this, clear the data store filter
this.store.clearFilter();
// --- Then call base class setValue() function
Ext.form.LocalComboBox.superclass.setValue.call(this, v);
}
});