【问题标题】:ExtJS : Re-selecting the same value does not fire the select eventExtJS:重新选择相同的值不会触发选择事件
【发布时间】:2018-10-26 15:54:15
【问题描述】:

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

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

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

我正在使用 ExtJS Classic 6.6.0。

编辑:我回答了我自己的问题并用可行的解决方案更新了 Fiddle。

【问题讨论】:

  • 为什么-1没有任何解释?

标签: javascript extjs


【解决方案1】:

试着看看这个: ExtJS 4 Combobox event for selecting selected value

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

【讨论】:

  • 谢谢,它给了我应该做什么的指示。我会用解决方案来回答我的问题,因为它与这个答案有点不同(我想要选择事件,而不是点击事件)。
【解决方案2】:

我找到了罪魁祸首:这一切都发生在组合框 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);
                }
            }
        }
    }
});

然后,只需在您的应用中使用扩展组合框即可。这样,每次都会触发 select 事件。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-04-16
    • 1970-01-01
    • 2015-11-03
    • 1970-01-01
    • 1970-01-01
    • 2018-03-05
    • 2012-03-12
    • 2018-02-24
    相关资源
    最近更新 更多