Extjs combobox: скрыть выбранное значение из выпадающего списка

Я использую ExtJS 4 и ищу способ скрыть выбранное значение из выпадающего списка combo?

поэтому вместо этого ("Аляска" в настоящее время выбрана в combobox):

default combobox behaviour

Я хочу, чтобы список значений выглядит так:

enter image description here

в моем случае combobox не редактируется (т. е. вы не можете ввести произвольное значение), я не думаю, что имеет смысл отображать выбранное значение два times: один раз в поле ввода и один раз в раскрывающемся списке. Я уже вижу, что выбрано, я хочу, чтобы выпадающий список только показывал мне другое параметры, которые я могу выбрать.

пока я не вижу простого способа сделать это. Вероятно, лучше всего начать с фильтрации combobox store, но combobox использует свои собственные фильтры для живого поиска.

кто-нибудь рассматривал эту проблему? Я пытаюсь сделать что-то странное? Я удивлен, что не смог ... найдите все связанные темы.

5 ответов


Я не думаю, что у вас есть много вариантов здесь... может быть, вы могли бы сделать что-то вроде этого:

Ext.define('Your.company.Combo', {
    extend: 'Ext.form.field.ComboBox',
    alias: 'widget.specialcombo',

    /**
    * @cfg {boolean} hideActive
    * True to hide any selected record. Defaults to <tt>true</tt>.
    */
    hideActive: true,

    /**
    * @private {Ext.data.Model[]} hideActive
    * A Array of selected records.
    */


    initComponent: function () {
        this.selectedRecords = [];

        this.callParent(arguments);

        this.on('select', this.onSelectionChange, this);
    },

    /**
    * @private onChangeSelection
    * eventhandler selections
    */
    onSelectionChange: function (me, recs) {
        if(!me.hideActive)
            return;
        // write the current selected back to the store (you need to suspend autoSync if active)
        me.store.add(me.selectedRecords);
        // set the selected as new recordlist
        me.selectedRecords = recs;
        // remove the selected from the store
        me.store.remove(recs);
    }
});

этот пример совершенно непроверенные. Но поскольку магазин в основном привязан к BoundList, который не связан напрямую с textfield, это должно работать. Вы делаете своего рода кэширование здесь.


Я придумал другое решение, которое выглядит еще проще, и быстрое тестирование не показывает никаких побочных эффектов:

мы можем оставить логику Combobox нетронутой, но просто скрыть выбранный элемент через CSS:

.x-boundlist-selected {
    display: none;
}

и вуаля, мы не видим выбранный товар! Не знаю, насколько это надежно в производственном коде, но все же стоит рассмотреть, Я думаю...


обновление. вот полное решение, если вы хотите контролировать это поведение через флаг конфигурации Combobox:

Ext.define('My.ComboBox',  {
    extend: 'Ext.form.field.ComboBox',

    /**
     * @cfg {Boolean} hideActive=true
     * When true, hides the currently selected value from the dropdown list
     */
    hideActive: true,

    /**
     * Internal method that creates the BoundList
     */
    createPicker: function() {
      var picker = this.callParent(arguments);

      // honor the hideActive flag
      if(this.hideActive) {
        picker.addCls('x-boundlist-hideactive');
      }

      return picker;
    }
});

где-то в вашем CSS:

.x-boundlist-hideactive .x-boundlist-selected {
    display: none;
}

обновление 2. Нашел проблему с UI с моим подходом!

скрытие выбранного элемента из выпадающего списка вводит причуду навигации по клавиатуре: хотя элемент визуально скрыт, он все еще существует, и Ext выберет его при нажатии клавиш вверх/вниз. Визуально это означает, что ваш выбор исчезнет в какой-то момент, и вам придется нажать Вверх / вниз еще раз, чтобы вернуть его на следующий видимый элемент.

до сих пор я не смог найти простое решение для этого. Лучше всего было бы изменить itemSelector связанного списка (который является представление данных), установив его на что-то вроде .x-boundlist-item:not(.x-boundlist-selected) таким образом, выбранный элемент не попадает в запрос.

хотя сам селектор работает, он не решает проблему, потому что представление выполняет этот запрос селектора перед любыми дополнительными классами (включая выбранный элемент class) применяется к элементам (это происходит в ВН.вид.AbstractView.refresh ().

кроме того, это решение вызывает смещение выпадающего списка список, когда он появляется над combobox!

у меня было ощущение, что мой подход слишком прост для безупречной работы:)


в итоге я использовал модифицированную версию решения @sra:

Ext.define('My.ComboBox',  {
    extend: 'Ext.form.field.ComboBox',

    /**
     * @cfg {Boolean} hideActive=true
     * When true, hides the currently selected value from the dropdown list
     */
    hideActive: true,

    /**
    * @private {Ext.data.Model[]} selectedRecords
    * A Array of selected records, used when hideActive is true
    */

    initComponent: function() {
        this.selectedRecords = [];

        this.callParent();
    },


    setValue: function(value, doSelect) {
        var store = this.store;

        if(this.hideActive) {
            store.suspendEvents(false);
            // write the current selected back to the store (you need to suspend autoSync if active)
            // do this BEFORE callParent so the currently selected record would be found in the store
            store.add(this.selectedRecords);
        }

        this.callParent(arguments);

        if(this.hideActive) {
            // set the selected as new recordlist
            this.selectedRecords = this.valueModels;
            // remove the selected from the store
            store.remove(this.valueModels);
            store.resumeEvents();
            store.fireEvent('refresh', store);
        }

        return this;
    }

});

логика "скрытия" такая же, только я выполняю ее в setValue метод, чтобы убедиться, что он также работает при программном задании значения combo, включая случай, когда combobox инициализируется значением.

UPD кроме того, похоже store.add(this.selectedRecords); называется до this.callParent(arguments);, в противном случае combobox будет действовать странно, если мы попытаемся установить в одно и то же значение дважды (он просто не найдет активную запись в магазине, потому что мы ее удалили, поэтому она будет сброшена на пустую). Я приостанавливаю события магазина, чтобы предотвратить некоторые причуды, вызванные combobox, пытающимся синхронизировать с его выпадающим списком в середине моих манипуляций с выбранными записями и вручную вызвать магазин 'refresh' событие, когда я закончу, чтобы список в конечном итоге обновился. Это может повлиять на производительность, но пока я не знаю лучшего решения.


ExtJS 3 я написал этот ответ на основе других. Отлично работает для меня, его немного изменен от того, что вы ищете, хотя.

Name.space.name = new Ext.extend(Ext.form.ComboBox, {
    type: 'all',
    oldrec: null,
    store: null,
    constructor: function (config) {
        var me = this;
        if (config.type === 'all') {
            me.store = AllConditionStore;
        } else {
            me.store = ?.?('RuleParameterType');
        }
        config = Ext.apply({
            store: me.store,
            valueField: 'id',
            hideActive: true,
            triggerAction: 'all',
            lazyRender: true,
            allowBlank: false,
            mode: 'local',
            displayField: 'text',
            listeners: {
                select: function (me, recs, index) {
                    if (me.oldrec !== null)
                        me.store.add(me.oldrec);
                    me.oldrec = recs;
                    // remove the selected from the store
                    me.store.remove(recs);
                    // redo store
                }
            }
        }, config);
        ?.?.Parameter.superclass.constructor.call(this, config);
    }
});

поэтому я использовал решение @sra, но с небольшой модификацией, чтобы добавить содержимое в нужное место ниже if(!me.hideActive):

if(me.selectedRecords[0]) {
    me.store.insert(me.selectedRecords[0].index,me.selectedRecords);
}

таким образом, вы просто не добавлять их в боты. Я знаю, что это старый пост, но я надеюсь, что это поможет людям искать решение.