Sencha Inc. | HTML5 Apps

ComboBox FAQ

Published Sep 17, 2010 | The Sencha Dev Team | FAQ | Medium
Last Updated Jul 11, 2011

This FAQ is most relevant to Ext JS, any version.

This article is currently due for review
We suspect that this article may be out-of-date or contain incorrect information.
But we are constantly editing articles, so we promise we will get to this one soon.

Load from remote store first time

If you need combos accessing large tables the remote store and using combo to search these tables is best solution. If the combo's mode is 'remote', it loads it's store on trigger click. Suggested procedure:

  • Configure grid. Combos have remote stores.
  • Special renderers are needed for fields with combos as with combo I actually edit/choose a kind of ID but I want to see/choose the related text. The delivered json contains both those ID and related texts.
  • If grid is in "display" mode the renderer takes care about displaying texts instead of IDs.
  • Once I enter edit mode (of a combo) and I click trigger the combo's store is loaded from server, list of texts (with underlying corresponding IDs) is displayed.
  • New ID goes to store and is submitted back to server (to be used there as a kind of foreign key) and text is displayed.

local/static store

  • If you need combos with mostly static data with a few records (language selector, theme selector, gender combo, currency combo would be good examples) the best is to deliver data for them with initial page load and treat them as in-memory data.
To show options in a combobox, you must load some data. You can load data from local data or from the server.

Have server generate this code in header before instantiation of combo(s):

YourScope.static.yourData = [
     [1, 'item1']
    ,[2, 'item2']
];
Or in the js file create a data store, like the following:
var yourData = [
     [1, 'item1']
    ,[2, 'item2']
];
  • To show this data in the combobox, configure combo(s) as follows: (set the mode property to local or to load from the server, set that property to remote-the default).
var combo = new Ext.form.ComboBox({
    store: new Ext.data.SimpleStore({
         id:0
        ,fields:
            [
                'myId',   //numeric value is the key
                'myText' //the text value is the value
            ]
        ,data:YourScope.static.yourData
    })
    ,valueField:'myId'
    ,displayField:'myText'
    ,mode:'local'
    // rest of config
});

load from store every time

  • There is no config option, you can delete the previous query in the beforequery event to set combo.lastQuery = null (this will reload the store the next time it expands), e.g.
var combo = new Ext.form.ComboBox({
    ...
    mode: 'remote',
    ...
    listeners: {
        beforequery: function(qe){
            delete qe.combo.lastQuery;
        }
    }
});

Need to do something when something in comboBox is selected

Configure the select event:

var cb = new Ext.form.ComboBox({
    // all of your config options
    listeners:{
         scope: yourScope,
         'select': yourFunction
    }
});

Alternatively, you can assign events after the object is created:

var cb = new Ext.form.ComboBox(yourOptions);
cb.on('select', yourFunction, yourScope);

linked comboBoxes

var modelRecord = new Ext.data.Record.create([{name: 'model'}]);
 
var brandJReader = new Ext.data.JsonReader({
                     totalProperty: 'brandCount',
                     root: 'brandData', 
                     id: 'brand'}, [{name: 'brand'}]);
 
var modelJReader = new Ext.data.JsonReader({
                     totalProperty: 'modelCount',
                     root: 'modelData', 
                     id: 'model'}, [{name: 'model'}]);
 
var brandStore = new Ext.data.Store({
  proxy: new Ext.data.HttpProxy(
    {url: 'some_url1',
    method: 'GET'}
  ),
  reader: brandJReader,
  autoLoad: true
});
 
var modelStore = new Ext.data.Store({
    {url: 'some_url2',
    method: 'GET'}
  ),
    reader: modelJReader
});
 
var formPanel = new Ext.FormPanel({
            title:'Choose car...',
            frame: true,
            width: 750,
            labelWidth: 175,
            style:'margin:5px 5px',
            bodyStyle:'padding:10px',
            defaults: {xtype:'combo'},          
            items:[ 
                     new Ext.form.ComboBox ({
                         fieldLabel:'Select Brand',
                         displayField:'brand',
                         valueField:'brand',
                         id: 'brands',
                         store: brandStore,
                         triggerAction:'all',
                         mode:'local',
                         listeners:{select:{fn:function(combo, value) {
                            var modelCmp = Ext.getCmp('models');
                            modelCmp.setValue('');
                            modelCmp.setDisabled(false);
                            modelCmp.store.reload({
                                params: { brand: combo.getValue() }
                            });
                         }}}                     
                     }), new Ext.form.ComboBox ({
                        fieldLabel:'Select Model',
                        displayField:'model',
                        valueField:'model',
                        id:'models',
                        disabled: true,
                        store: modelStore,
                        triggerAction:'all',
                        mode:'local',
                        autoHeight: true
                     })
            ],
            buttons: [
                    {
                        text: 'Get Car'
                    }
            ]     
});
 
var centerSide = new Ext.TabPanel({
                    region:'center',
                    split:true,
                    height: 600,
                    deferredRender:false,
                    activeTab:0,
                    margins:'0 0 0 5',
                    items:[{
                        contentEl:'carTab',
                        title: 'Cars',
                        autoScroll:true,
                        items: [formPanel]
                    },{
                        contentEl:'mcTab',
                        title: 'Motorcycles',
                        autoScroll:true
                    }]
});

Manipulating comboBox data (escaping strings)

  • When rendering an Ext.form.ComboBox with data read from a JsonStore it may contain some special characters that need to be escaped and then unescaped before rendering to a comboBox.
  • Possible solution:
var store = new Ext.data.JsonStore({
   url: 'myurl',
   reader: new Ext.data.JsonReader(
      {
          root: 'data'  
      },
 
      //fields:
      [
         {name:'id'},
         {
            name:'title',
            convert: function(v){
               //manipulate v here
               console.log('Converting the title, where v = ',v);
               return unescape(v);
            }
         }
      ]
   )
});
 
store.on('load', function(s, r) {
   Ext.each(r, function(rec) {
      rec.data.title = unescape(rec.data.title);
   });
});
 
var combo = new Ext.form.ComboBox({
   id: 'combo1',
   applyTo: 'mycombo',
   store: store,
   valueField:'id',
   displayField: 'title',
   hideTrigger:false,  
   triggerAction: 'all'
});

Do something when comboBox value changes

ComboBox has a change or select event that you want to subcribe to.

listeners:{
  change:function(combo, ewVal, oldVal) {
    // do something
  }
}to the config of your ComboBox.

Form submits displayField instead of valueField

  • the store has to be loaded BEFORE setValue(). Try this patch:
Ext.override(Ext.form.ComboBox, {
    setValue : function(v){
//begin patch
        // Store not loaded yet? Set value when it *is* loaded.
        // Defer the setValue call until after the next load.
        if (this.store.getCount() == 0) {
            this.store.on('load',
                this.setValue.createDelegate(this, [v]), null, {single: true});
            return;
        }
//end patch
        var text = v;
        if(this.valueField){
            var r = this.findRecord(this.valueField, v);
            if(r){
                text = r.data[this.displayField];
            }else if(this.valueNotFoundText !== undefined){
                text = this.valueNotFoundText;
            }
        }
        this.lastSelectionText = text;
        if(this.hiddenField){
            this.hiddenField.value = v;
        }
        Ext.form.ComboBox.superclass.setValue.call(this, text);
        this.value = v;
    }
});

submit "valueField" instead of "displayField"

Other threads with solutions

Share this post:
Leave a reply

Written by The Sencha Dev Team

Commenting is not available in this channel entry.