在 Extjs6 的组合框中有 "Empty" 选项的最干净的方法是什么?

What is the cleanest way to have "Empty" option in a combobox in Extjs6?

我有一个由 ajax 商店支持的基本组合框。我希望能够 select 组合中的一个空值作为一个选项(它不作为商店中的记录存在)。设置 emptyText: 'None' 将是完美的,唯一的问题是一旦你 select 输入了一些值,你就不能再 select 一个空值了。

有没有比监听存储负载和注入额外的空记录或类似性质的东西更好的选择。我不想在该商店中永久保留空记录,仅当在某些组合框中使用时。

{
    xtype: 'combo',
    queryMode: 'local',
    triggerAction: 'all',
    forceSelection: true,
    editable: false,
    emptyText: 'None',
    store: 'MyStore',
}

我是这样做的:

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

  xtype: 'emptyable_combobox',

  uses: [ 'Ext.view.BoundList' ],

  /** The source is used to hold the original store. */
  _source: null,

  editable: false, // must pick from an item in the list
  allowBlank: true, // obviously can't be required, as the user can reset to blank.

  initComponent: function() {
    this._source = this.getStore();

    var newData = [ 
      this._toEntry(null, null)
    ];

    this._source.each(function(record) {
      newData.push(this._toEntry(record.get(this.valueField), record.get(this.displayField)));
    }, this)

    this.store = new Ext.data.Store({
      fields: [ this.valueField, this.displayField ],
      data: newData
    });


    var itemCls = Ext.view.BoundList.prototype.itemCls;
    var innerTpl = Ext.view.BoundList.prototype.getInnerTpl;
    this.listConfig = Ext.apply({
      tpl: new Ext.XTemplate(
          '<ul class="' + Ext.plainListCls + '">',
          '<tpl for=".">',
            '<li role="option" unselectable="on" class="' + itemCls + '">',
              '<tpl if="name == null">',
                '<em>' + this.emptyText + '</em>',
              '<tpl else>',
                innerTpl(this.displayField),
              '</tpl>',
            '</li>',
            '<tpl if="name == null">',
              '<hr />',
            '</tpl>',
          '</tpl>',
          '</ul>'
        )
    }, this.listConfig);

    this.callParent(arguments);
  },

  _toEntry: function(value, display) {
    var result = {}
    result[this.valueField] = value;
    result[this.displayField] = display;
    return result;
  }
})

如果您需要支持对原始商店的过滤,则需要做一些更复杂的事情,但这应该为您指明方向。

请注意,如果您的 ComboBox 是 editable(例如,您允许用户在其中键入内容),他们可以通过清除文本来简单地设置一个空值。这就是此实现将 editable 值硬编码为 false 的原因。

我通过创建插件实现了这一点。

Ext.define("App.ux.plugin.form.field.EmptiableComboBox", {
    extend : 'Ext.AbstractPlugin',
    alias : 'plugin.emptiableCombo',
    init : function(combo) {
        this.combo = combo;
        this.callParent();
        combo.addListener('change', function() {
            if (this.getValue() === null || this.getValue() == '') {
                this.reset();
                this.setRawValue(null);
                this.lastSelection = [];
            }
        });
    }
});

下面是我的使用方法。

{   
    type:'combobox',
    typeAhead:true,
    plugins: ['emptiableCombo'],
    listConfig:{
        cls:'x-combo-boundlist-small'
    }
}

更新: 我之前已经完成了这个练习,可以肯定的是我们不想添加一个空值选项。所以我们剩下 2 个选项

  1. 为可以清空的连击添加清除触发器。
  2. 使 Combobox 可编辑并启用 forceSelection,这样用户可以很容易地输入值以进行自动选择,并且如果该字段是可选的,他还可以清除值。启用 forceSelection 后,用户无法输入任意值。

然后我们选择了选项 2 并创建了这个插件。如果您有任何其他更好的解决方案,请在此处 post 执行此操作。谢谢