ExtJS: Повторный выбор того же значения не вызывает событие выбора - PullRequest
0 голосов
/ 25 октября 2018

Обычно, когда вы выбираете элемент в выпадающем списке, вы ожидаете, что он вызовет событие выбора.Однако, если вы попытаетесь выбрать элемент, который уже был выбран, событие select не будет запущено.Это "нормальное" поведение комбинированного списка ExtJs.

У меня есть особая потребность в комбинированном окне ExtJS: он мне нужен, чтобы вызвать событие select, даже если я повторно выбрал то же значение.Но я не могу заставить его работать.Любая помощь будет принята с благодарностью!

Пример здесь: https://fiddle.sencha.com/#view/editor&fiddle/2n11 Откройте инструменты разработчика, чтобы увидеть, когда происходит событие select.

Я использую ExtJS Classic 6.6.0.

Редактировать: Я ответил на свой вопрос и обновил Fiddle с рабочим решением.

Ответы [ 2 ]

0 голосов
/ 25 октября 2018

Я нашел виновника: все это происходит в SelectionModel комбинированного списка BoundList, в методе 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 будет запускаться каждый раз.

0 голосов
/ 25 октября 2018

попробуйте взглянуть на это: Событие ExtJS 4 Combobox для выбора выбранного значения

Это для более ранней версии ExtJS, но перехват события click для элемента списка тоже может вам помочь.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...