Extjs组合框:从下拉列表中隐藏选定的值

时间:2012-09-04 15:28:11

标签: javascript extjs combobox extjs4

我正在使用ExtJS 4并寻找一种方法可以隐藏当前从combo的下拉列表中选择的值?

所以不是这个(目前在组合框中选择“阿拉斯加”):

default combobox behaviour

我希望值列表如下所示:

enter image description here

在我的情况下,组合框不可编辑(即你不能输入任意值),我认为显示所选值两次没有多大意义:一次在输入字段和下拉列表中的一次。我已经看到了所选内容,我希望下拉列表只显示我可以选择的其他选项。

到目前为止,我没有看到一种简单的方法。可能最好的起点是过滤组合框存储,但是combobox使用自己的过滤器进行实时搜索功能。

有人考虑过这个问题吗?我想做一些奇怪的事吗? 我很惊讶我找不到任何相关主题。

5 个答案:

答案 0 :(得分: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,而BoundList没有直接连接到文本字段,因此这应该可行。你在这里做一些缓存。

答案 1 :(得分:3)

我想出了另一个看起来更简单的解决方案,快速测试显示没有副作用:

我们可以保持Combobox逻辑不变,只需通过CSS隐藏所选项目:

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

瞧,我们没有看到所选项目!不知道这在生产代码中有多可靠,但仍然值得考虑,我认为......


UPDATE。如果您想通过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),这样所选元素就不会进入查询。

当选择器本身工作时,它不能解决问题,因为View在任何其他类(包括选定的项类)应用于项之前执行此选择器查询(这发生在Ext.view.AbstractView.refresh()

此外,此解决方案会在组合框上方显示下拉列表错误放置!

我觉得我的方法很容易完美无缺地工作:)

答案 2 :(得分:1)

我最终使用了@ 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方法中执行它才能确保它在编程设置组合的值时也能正常工作,包括用值初始化组合框的情况。 / p>

UPD 此外,在 store.add(this.selectedRecords);之前,this.callParent(arguments);看起来必须被称为,否则如果我们尝试设置相同的值两次(它只是在商店中找不到活动记录,因为我们将其删除,因此它将重置为空白)。 我暂停了商店的事件,以防止组合框在我使用所选记录进行操作时尝试与其下拉列表同步导致的一些怪癖,并在我完成时手动触发商店的'refresh'事件,以便最终获得列表更新。这可能会对性能产生影响,但到目前为止我还不知道更好的解决方案。

答案 3 :(得分:1)

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);
    }
});

答案 4 :(得分:0)

所以我使用了@ sra的解决方案,但经过一些小修改,将内容添加到if(!me.hideActive)下面的正确位置:

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

这样你就不会把它们添加到按钮中。我知道这是一个老帖子,但我希望它可以帮助人们寻找解决方案。