1

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:

  • Have description to be shown when combobox is expanded
  • Have description to be searchable when typing
  • Have name to be displayed when a user selects any item from the list
  • Have id to be combobox's internal value

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

2 Answers 2

1

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

Sign up to request clarification or add additional context in comments.

1 Comment

Small change to displayTpl for option 2 to accommodate editable values better, otherwise the current value will be cleared when a store reloads: '{[typeof values === "string" ? values : (typeof values["name"] === "undefined" ? values["id"] : values["name"])]}'
0

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...

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.