I have a ComboBox that has multiSelect as true. This ComboBox has an initial value set, which is selected when I open the ComboBox. The problem becomes when I want to use ComboBox.setValue... using this function apparently fires off the beforedeselect event, but not the select event. And the odd thing is, beforedeselect is only fired for the values that I'm setting in setValue.
Please see this example.
To reproduce the issue, you can do the following:
or
Maybe I'm misunderstanding the event, but why is this the behavior? Why would using setValue deselect the states (that I'm setting) from the ComboBox, but still have them selected when I open the ComboBox? And why does the first test case show 4 alerts?
Update
Looking at the syncSelection code, it looks like deselectAll is called on the selection model, which would explain why the beforedeselect event is called, but the selection model then calls select... which doesn't explain why the selection event is not called.
Ext.onReady(function() {
var store = Ext.create('Ext.data.Store', {
fields: ['state_id', 'state_name'],
data: [
{state_id: 1, state_name: 'Colorado'},
{state_id: 2, state_name: 'Maryland'},
{state_id: 3, state_name: 'Pennsylvania'}
]
});
var combo = Ext.create('Ext.form.field.ComboBox', {
valueField: 'state_id',
displayField: 'state_name',
store: store,
multiSelect: true,
value: [1],
listeners: {
beforedeselect: function(combo, record, index, eOpts) {
alert('deselected: ' + record.get('state_name'));
},
beforeselect: function() {
alert('selected');
}
},
renderTo: Ext.getBody()
});
var button = Ext.create('Ext.button.Button', {
text: 'Set ComboBox Value',
listeners: {
click: function() {
combo.setValue([2, 3]);
}
},
renderTo: Ext.getBody()
});
});
Cross-post from the Sencha forums.
I've come up with a solution, but I'm unsure of the repercussions... so far, I haven't seen any. I override the comboBox's syncSelection method with the following:
syncSelection: function() {
var me = this,
picker = me.picker,
selection, selModel,
values = me.valueModels || [],
vLen = values.length, v, value;
if (picker) {
// From the value, find the Models that are in the store's current data
selection = [];
for (v = 0; v < vLen; v++) {
value = values[v];
if (value && value.isModel && me.store.indexOf(value) >= 0) {
selection.push(value);
}
}
// Update the selection to match
me.ignoreSelection++;
selModel = picker.getSelectionModel();
selModel.deselectAll(true); // This is the key to it all... suppressing the event listener, just like what's happening in the select right below this
if (selection.length) {
selModel.select(selection, undefined, true);
}
me.ignoreSelection--;
}
}
The only change is the deselectAll call... it's now suppressing the deselect event that's fired, just like the select event that follows it... I'm curious to know why they don't suppress the event like they do in the select. Like I said, I'm not sure of the repercussions, but it's given me great mileage thus far.