Colin
Colin

Reputation: 1855

ExtJS: Custom ComboBox

I'm just trying to create a custom ComboBox to reduce some boilerplate:

Ext.define('App.AutoComboBox', {
    extend: 'Ext.form.field.ComboBox',
    alias: 'widget.autocombobox',

    states: null,

    initComponent: function() {
        this.callParent(arguments);
        if (!this.states) {
            this.queryMode = 'remote';
        } else {
            this.queryMode = 'local';
            this.bindStore(Ext.create('Ext.data.Store', {
                type: 'array',
                fields: ['_placeholder_'],
                data: _.map(this.states, function(state) {
                    return {_placeholder_ : state}; })
            }));
            this.displayField = this.valueField = '_placeholder_'
        }
        this.validator =  function(v) {
            var field = this.displayField,
                index = this.getStore().findExact(field, v);
            return (index!==-1) ? true : 'Invalid selection';
        };
    },
    listeners: {
        select: function(combo, records) {
            console.log(combo.getStore().indexOf(records[0])); // !== -1
        }
    }
});

So that I can use it like:

requires: ['App.AutoComboBox'],
...
items: [{
    xtype: 'autocombobox',
    name: 'test_local',
    fieldLabel: 'test_local',
    states: [ 'cat', 'dog' ]  // local
}, {
    xtype: 'autocombobox',
    name: 'test_remote',
    fieldLabel: 'test_remote',
    store: 'Chipmunks', // a remote store
    displayField: 'chipmunk_name'
}]
...

But something is amiss. The AutoComboBox renders OK, shows dropdown of records fine, but when I select an item from the dropdown, the combobox's display field is not set. The store seems to find the selected record (as seen by the select listener), but the value is still not set...

Help? thanks.

Edit: FIXED by moving this.callParent(arguments) after the new store is bound. Now accepting answers that explain why this fixes it... (I don't know why it works.. but it does)

Upvotes: 1

Views: 2870

Answers (1)

rixo
rixo

Reputation: 25031

In the parent initComponent method, the displayField is used to create the displayTpl:

    if (!me.displayTpl) {
        me.displayTpl = new Ext.XTemplate(
            '<tpl for=".">' +
                '{[typeof values === "string" ? values : values["' + me.displayField + '"]]}' +
                '<tpl if="xindex < xcount">' + me.delimiter + '</tpl>' +
            '</tpl>'
        );
    } else if (Ext.isString(me.displayTpl)) {
        me.displayTpl = new Ext.XTemplate(me.displayTpl);
    }

The bindStore call has probably nothing to do with it, I believe that this is this line that must be put before the call to the parent method:

this.displayField = this.valueField = '_placeholder_';

Upvotes: 2

Related Questions