2012-09-04 89 views
7

我正在使用ExtJS 4并寻找一种方法,可以从组合的下拉列表中隐藏当前选定的值?Extjs组合框:从下拉列表中隐藏选定的值

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

default combobox behaviour

我希望值的列表如下所示:

enter image description here

在我的情况下,组合框是不可编辑(即你不能输入一个任意值),我不认为这显示选定的值两次是很有意义的:一旦在内把字段和一次在下拉列表中。我已经看到选择了什么,我想要下拉列表只显示我其他选项我可以选择。

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

有人认为这个问题?我想做些奇怪的事情吗? 我很惊讶,我一直没有找到任何相关的主题。

+0

在Sencha的论坛上提出同样的问题:http://www.sencha.com/forum/showthread.php?241063-Combobox-hide-selected-value-from-dropdown-list&p=882210 –

回答

1

我结束了使用修改版本的@ sra的如此lution:

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方法来执行它,以确保它也可以当编程设定组合的价值,包括在组合框与值初始化的情况下, 。

UPD此外,貌似store.add(this.selectedRecords);有被称为this.callParent(arguments);之前,否则,如果我们尝试设置相同值的两倍(它根本不会发现在店里的活动记录组合框将采取行动怪异导致我们删除它,所以它将重置为空白)。 我暂停商店的事件,以防止组合框引起的一些怪癖试图与我的操作与选定的记录(s)中下拉列表同步和手动触发商店的'refresh'事件时,我完成了,因此列表最终得到更新。这可能会对性能产生影响,但到目前为止我还不知道更好的解决方案。

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,因此应该可以工作。你正在这里做一种缓存。

+0

这个想法看起来不错我但代码不起作用。 'this.on('select',function(){this.onSelectionChange();},this);'应该改为'this.on('select',this.onSelectionChange,this);'让它工作正确地说'hideActive:false'也没有效果。 – pllee

+0

感谢您的建议。我监督了这些事情。修复是 – sra

+0

谢谢,这似乎是伎俩!编辑你的代码一点,现在它的功能。 –

3

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

我们可以把组合框的逻辑不变,而只是通过CSS隐藏选定项目:

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

而且瞧,我们没有看到选定的项目!不知道怎么可靠,这将是在生产代码,但还是值得考虑的,我想......


更新。下面是完整的解决方案,如果你想控制通过组合框的配置将此行为:

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

UPDATE 2.发现一个UI问题我的方法!

从下拉列表中隐藏选定的项目引入了键盘导航的怪癖:尽管该元素在视觉上隐藏,但它仍然存在,并且按下UP/DOWN键时Ext将选择它。在视觉上,这意味着你的选择会在某个时候消失,你将不得不再次按下UP/DOWN来重新显示下一个可见元素。

到目前为止,我无法找到一个简单的解决方案。 我最好的办法是修改绑定列表(这是一个数据视图)的itemSelector,将其设置为.x-boundlist-item:not(.x-boundlist-selected)之类的东西,以便所选元素不会将其添加到查询中。

而选择自己的工作,因为视图执行之前的任何其他类此选择查询(包括所选项目类),它并没有解决这个问题得到应用到项目(这发生在Ext.view.AbstractView.refresh()

此外,该解决方案将导致下拉列表错位,当它出现在组合框上面!

我有一种感觉,我的做法是太容易工作得很好:)

+0

好点,我猜更快。从来没有尝试过。 – sra

+0

我会留下现在不被接受的答案,好奇是否有人想出其他想法... –

+0

这完全取决于你:)但是你可以晚些时候不接受答案。这就像信息 – sra

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

所以我用@ SRA解决方案,但有一个小的修改,以在适当的地方加上下面的if(!me.hideActive)内容:

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

这样,你只是不将它们添加到钮。我知道这是一个旧帖子,但我希望它能帮助寻找解决方案的人。

相关问题