serg
serg

Reputation: 111265

How to have combobox to select different value than displayed in ExtJS6?

I have a basic combobox linked to a store with 3 fields: id, name, and description. I am trying to make combobox to behave like this:

The following config solves almost everything except description being searchable:

{
    xtype: 'combo',
    queryMode: 'local',
    triggerAction: 'all',
    forceSelection: false,
    editable: true,
    anyMatch: true,
    valueField: 'id',
    displayField: 'name',
    listConfig: {
        itemTpl: '{description}'
    },
    store: store,
},

Upvotes: 1

Views: 2106

Answers (2)

JChap
JChap

Reputation: 1441

Option 1:

You can override the Combobox - doLocalQuery method and add support for one more property like searchField. Only change that i did in this method is replaced property: me.displayField, with

property: me.searchField || me.displayField,

If searchField is configured then it will use the search field otherwise it fallbacks to regular displayField.

Ext.define('App.override.form.field.ComboBox', {
    override: 'Ext.form.field.ComboBox',


    doLocalQuery: function(queryPlan) {
        var me = this,
            queryString = queryPlan.query,
            store = me.getStore(),
            filter = me.queryFilter;

        me.queryFilter = null;

        // Must set changingFilters flag for this.checkValueOnChange.
        // the suppressEvents flag does not affect the filterchange event
        me.changingFilters = true;
        if (filter) {
            store.removeFilter(filter, true);
        }

        // Querying by a string...
        if (queryString) {
            filter = me.queryFilter = new Ext.util.Filter({
                id: me.id + '-filter',
                anyMatch: me.anyMatch,
                caseSensitive: me.caseSensitive,
                root: 'data',
                // use searchField if available or fallback to displayField
                property: me.searchField || me.displayField,
                value: me.enableRegEx ? new RegExp(queryString) : queryString
            });
            store.addFilter(filter, true);
        }
        me.changingFilters = false;

        // Expand after adjusting the filter if there are records or if emptyText is configured.
        if (me.store.getCount() || me.getPicker().emptyText) {
            // The filter changing was done with events suppressed, so
            // refresh the picker DOM while hidden and it will layout on show.
            me.getPicker().refresh();
            me.expand();
        } else {
            me.collapse();
        }

        me.afterQuery(queryPlan);
    }
});

And this will be combo config

{
    xtype: 'combo',
    queryMode: 'local',
    triggerAction: 'all',
    forceSelection: false,
    editable: true,
    anyMatch: true,
    valueField: 'id',
    displayField: 'name',
    searchField: 'description',
    listConfig: {
        itemTpl: '{description}'
    },
    store: store,
},

https://fiddle.sencha.com/#fiddle/17lc

Option 2:

Configure the displayField as description and just configure the displayTpl to use the "name" property. More over you can remove the listConfig as well.

{
    xtype: 'combo',
    queryMode: 'local',
    triggerAction: 'all',
    forceSelection: false,
    editable: true,
    anyMatch: true,
    valueField: 'id',
    displayField: 'description',
    displayTpl: new Ext.XTemplate(
        '<tpl for=".">' +
        '{[typeof values === "string" ? values : values["name"]]}' +
        '</tpl>'
    ),
    store: store,
}

https://fiddle.sencha.com/#fiddle/17ld

Upvotes: 1

Yasuyuki  Uno
Yasuyuki Uno

Reputation: 2547

How about this?

{
    xtype: 'combo',
    queryMode: 'local',
    triggerAction: 'all',
    forceSelection: false,
    editable: true,
    anyMatch: true,
    valueField: 'id',
    displayField: 'name',
    listConfig: {
        itemTpl: '{description}'
    },
    store: store,
    listeners: {
        change: function() {
          var store = this.store;
          store.clearFilter();
          store.filter({
              property: 'description',
              anyMatch: true,
              value   : this.getRawValue()
          });

          this.expand();
        }
    }
},

https://fiddle.sencha.com/#fiddle/17ks

Update: The above code looks good while typing.
But after select some data, it can't expand because of filtered...

I tried below code, too. The 2nd example.

listeners: {
    keyup: function() {
      var store = this.store;
      store.clearFilter();
      store.filter({
          property: 'description',
          anyMatch: true,
          value   : this.getRawValue()
      });

      this.expand();
    },
    collapse: function() {
      var store = this.store;
      // Reset filter here.
      store.clearFilter();
    }
},

2nd Example Run at fiddle: https://fiddle.sencha.com/#fiddle/17ku

I feel the 2nd code is better than 1st. But it also doesn't work perfectly...

Upvotes: 0

Related Questions