ExtJS :重新选择相同的值不会触发选择事件



>通常,当您在组合框中选择一个项目时,您会期望它触发 select 事件。但是,如果尝试选择已选择的项,则不会触发 select 事件。这是 ExtJs 组合框的"正常"行为。

我对 ExtJS 组合框有特殊需求:即使我重新选择相同的值,我也需要它来触发选择事件。但我无法让它工作。任何帮助将不胜感激!

此处的示例:https://fiddle.sencha.com/#view/editor&fiddle/2n11 打开开发工具以查看何时触发选择事件。

我正在使用 ExtJS Classic 6.6.0。

编辑:我回答了自己的问题,并用工作解决方案更新了小提琴。

尝试查看以下内容: 用于选择所选值的 ExtJS 4 组合框事件

它适用于早期的 ExtJS 版本,但捕获 itemlist 的点击事件也可能对您有所帮助。

我找到了罪魁祸首:这一切都发生在组合框 BoundList 的 SelectionModel 中,在方法 doSingleSelect 中。

因此,如果我们扩展 Ext.Selection.DataViewModel 和 Ext.form.field.ComboBox,我们可以强制每次都触发 select 事件。

Ext.define( "MyApp.selection.DataViewModelExt", {
"extend": "Ext.selection.DataViewModel",
"alias": "selection.dataviewmodelext",
"doSingleSelect": function(record, suppressEvent) {
var me = this,
changed = false,
selected = me.selected,
commit;
if (me.locked) {
return;
}
// already selected. 
// should we also check beforeselect? 
/*
if (me.isSelected(record)) {
return;
}
*/
commit = function() {
// Deselect previous selection. 
if (selected.getCount()) {
me.suspendChanges();
var result = me.deselectDuringSelect([record], suppressEvent);
if (me.destroyed) {
return;
}
me.resumeChanges();
if (result[0]) {
// Means deselection failed, so abort 
return false;
}
}
me.lastSelected = record;
if (!selected.getCount()) {
me.selectionStart = record;
}
selected.add(record);
changed = true;
};
me.onSelectChange(record, true, suppressEvent, commit);
if (changed && !me.destroyed) {
me.maybeFireSelectionChange(!suppressEvent);
}
}
});

我们还必须扩展组合框以强制使用扩展的 DataViewModel。唯一要更改的是 onBindStore 方法,它实例化了 DataViewModel:

Ext.define( "MyApp.form.field.ComboBoxEx", {
"extend": "Ext.form.field.ComboBox",
"alias": "widget.comboboxex",
"onBindStore": function(store, initial) {
var me = this,
picker = me.picker,
extraKeySpec,
valueCollectionConfig;
// We're being bound, not unbound... 
if (store) {
// If store was created from a 2 dimensional array with generated field names 'field1' and 'field2' 
if (store.autoCreated) {
me.queryMode = 'local';
me.valueField = me.displayField = 'field1';
if (!store.expanded) {
me.displayField = 'field2';
}
// displayTpl config will need regenerating with the autogenerated displayField name 'field1' 
if (me.getDisplayTpl().auto) {
me.setDisplayTpl(null);
}
}
if (!Ext.isDefined(me.valueField)) {
me.valueField = me.displayField;
}
// Add a byValue index to the store so that we can efficiently look up records by the value field 
// when setValue passes string value(s). 
// The two indices (Ext.util.CollectionKeys) are configured unique: false, so that if duplicate keys 
// are found, they are all returned by the get call. 
// This is so that findByText and findByValue are able to return the *FIRST* matching value. By default, 
// if unique is true, CollectionKey keeps the *last* matching value. 
extraKeySpec = {
byValue: {
rootProperty: 'data',
unique: false
}
};
extraKeySpec.byValue.property = me.valueField;
store.setExtraKeys(extraKeySpec);
if (me.displayField === me.valueField) {
store.byText = store.byValue;
} else {
extraKeySpec.byText = {
rootProperty: 'data',
unique: false
};
extraKeySpec.byText.property = me.displayField;
store.setExtraKeys(extraKeySpec);
}
// We hold a collection of the values which have been selected, keyed by this field's valueField. 
// This collection also functions as the selected items collection for the BoundList's selection model 
valueCollectionConfig = {
rootProperty: 'data',
extraKeys: {
byInternalId: {
property: 'internalId'
},
byValue: {
property: me.valueField,
rootProperty: 'data'
}
},
// Whenever this collection is changed by anyone, whether by this field adding to it, 
// or the BoundList operating, we must refresh our value. 
listeners: {
beginupdate: me.onValueCollectionBeginUpdate,
endupdate: me.onValueCollectionEndUpdate,
scope: me
}
};
// This becomes our collection of selected records for the Field. 
me.valueCollection = new Ext.util.Collection(valueCollectionConfig);
// This is the selection model we configure into the dropdown BoundList. 
// We use the selected Collection as our value collection and the basis 
// for rendering the tag list.
//me.pickerSelectionModel = new Ext.selection.DataViewModel({
me.pickerSelectionModel = new MyApp.selection.DataViewModelExt({
mode: me.multiSelect ? 'SIMPLE' : 'SINGLE',
// There are situations when a row is selected on mousedown but then the mouse is dragged to another row 
// and released.  In these situations, the event target for the click event won't be the row where the mouse 
// was released but the boundview.  The view will then determine that it should fire a container click, and 
// the DataViewModel will then deselect all prior selections. Setting `deselectOnContainerClick` here will 
// prevent the model from deselecting. 
ordered: true,
deselectOnContainerClick: false,
enableInitialSelection: false,
pruneRemoved: false,
selected: me.valueCollection,
store: store,
listeners: {
scope: me,
lastselectedchanged: me.updateBindSelection
}
});
if (!initial) {
me.resetToDefault();
}
if (picker) {
me.pickerSelectionModel.on({
scope: me,
beforeselect: me.onBeforeSelect,
beforedeselect: me.onBeforeDeselect
});
picker.setSelectionModel(me.pickerSelectionModel);
if (picker.getStore() !== store) {
picker.bindStore(store);
}
}
}
}
});

然后只需在您的应用程序中使用扩展的组合框即可。通过这样做,每次都会触发选择事件。

最新更新