ExtJS 4: Combo Boxes, loadRecord() and Remote Stores

TV Remote

A while back I ran into an interesting issue regarding loading records from the database into a form that contained combo boxes driven by remote stores. The problem was, when the record got loaded into the form, the stores for the combo boxes hadn’t loaded, so all the combo boxes said “select one” instead of the option that was chosen when the form got submitted. After doing some digging, I came up with a way around this issue:

The Override Code

Ext.form.field.ComboBox.override( {
    setValue: function(v) {
        v = (v && v.toString) ? v.toString() : v;
        if(!this.store.isLoaded && this.queryMode == 'remote') {
            this.store.addListener('load', function() {
                this.store.isLoaded = true;
                this.setValue(v);
            }, this);
           this.store.load();
        } else {
            this.callOverridden(arguments);
        }
    }
});

Here, we override the setValue method of the ComboBox component and do the following:

  1. Make sure the store is not yet loaded (a custom property I added) and that it is tied to a remote store
  2. Add a listener to the ‘load’ event. When the store is loaded, set isLoaded equal to true and call setValue again.
  3. Load the store
  4. If the store is already loaded or the store is local, call the original overridden setValue method

Just drop this into whatever JS file you keep your other overrides in and you’ll be good to go. Happy coding!

Update: The source code for this snippet is available here.

  • http://www.twitter.com/catalinbanu Catalinux

    One problem is that a lot of change events appear on that combobox once you have made that override. I try to use it for a combobox grid cell editor where I have an POST onChange. This makes a lot of POSTs

  • http://blog.AgileHobo.com Agile Hobo

    Fix typo: View should not create Store directly.

    And of course, you must set Store’s autoLoad property to true

  • http://blog.AgileHobo.com Agile Hobo

    Don’t need to override, you only need to pass the store to Ext.widget(). Actually it’s my prefer way to load data. View should not work with Store directly.

    • martijn

      I’m Interested in the ext.widget() solution. I do not follow what you mean by passing store to it…. and how it would work to fix this problem, I’m seeking for a solution without overrides.

  • soravengeur

    Hello, a little improvement.
    With your method, when I use the autocompletion, it’s clear all value in the field when I begin to write. Here the correction :

    if(!this.store.isLoaded && typeof(v) != “undefined”) {
    v = (v && v.toString) ? v.toString() : v;
    this.store.addListener(‘load’, function() {
    this.store.isLoaded = true;
    if (!this.store.firstLoad) {
    this.setValue(v);
    this.store.firstLoad = true;
    }
    }, this);
    this.store.load();
    } else {
    this.callOverridden(arguments);
    }

  • arcan9ne

    This is a nice hack, I had to remove:
    v = (v && v.toString) ? v.toString() : v;

    because the value field is an integer for me. Maybe there is a reason I don’t see behind this.

    One strange thing that is occuring is that the store of a combo is loading when rendered and the setValue() is not being called.

  • http://ibe-erp Santosh

    Hi Puneet

    You can use the record option of the json parser.

  • http://ibe-erp Puneet

    Hi,

    Nice post, i am facing one problem with combo box, hope you could help me/

    i have a nested json in form of data { ‘id’:’1′,[{‘descr’:’this is id’}]} .

    how i can display descr as displayField in combo and id as valueField ?

    Thanks

  • http://rockstown.com Conor

    Nice override. One issue though. If you are viewing a form and not making any amendments, then this code is going to automatically load the store necessitating another trip to the server. A better solution might be the Ext.ux.form.AutoCombo

    • arcan9ne

      Any ideas on what could be done to circumvent one the unnecessary trips (other than Ext.ux.form.AutoCombo)?

      Thanks,
      arcan9ne