开发者

EXTJS 3.2.1 EditorGridPanel - ComboBox with jsonstore

I am using EXTJS with an editorgridpanel and I am trying to to insert a combobox, populated with JsonStore. Here is a snapshot of my code: THE STORE:

kmxgz.ordercmpappro.prototype.getCmpapproStore = function(my_url) {
 var myStore = new Ext.data.Store({
  proxy: new Ext.data.HttpProxy({
       url: my_url
     , method: 'POST'
    })
  , reader: new Ext.data.JsonReader({
         root: 'rows',
         totalProperty: 'total',
         id: 'list_cmpappro_id',
         fields: [
                    {name: 'list_cmpappro_id', mapping: 'list_cmpappro_id'}
                   , {name: 'list_cmpappro_name', mapping: 'list_cmpappro_name'}
             ]
      })
  , autoLoad: true
    , id: 'cmpapproStore'
     , listeners: {
                load: function(store, records, options){
              //store is loaded, now you can work with it's records, etc.
              console.info('store load, arguments:', arguments);
              console.info('Store count = ', store.getCount());
       }
       }
 });
 return myStore;
};

THE COMBO:

kmxgz.ordercmpappro.prototype.getCmpapproCombo = function(my_store) {
 var myCombo = new Ext.form.ComboBox({
     typeAhead: true,
     lazyRender:false,
      forceSelection: true,
     allowBlank: true,
     editable: true,
      selectOnFocus: true,
      id: 'cmpapproCombo',
     triggerAction: 'all',
     fieldLabel: 'CMP Appro',
     valueField: 'list_cmpappro_id',
     displayField: 'list_cmpappro_name',
     hiddenName: 'cmpappro_id',
  valueNotFoundText: 'Value not found.',
     mode: 'local',
     store: my_store,
     emptyText: 'Select a CMP Appro',
        loadingText: 'Veuillez patienter ...',        
     listeners: {

                // 'change' will be fired when the value has changed and the user exits the ComboBox via tab, click, etc.
                // The 'newValue' and 'oldValue' params will be from the field specified in the 'valueField' config above.
                change: function(combo, newValue, oldValue){
                    console.log("Old Value: " + oldValue);
                    console.log("New Value: " + newValue);
                },

                // 'select' will be fired as soon as an item in the ComboBox is selected with mouse, keyboard.
                select: function(combo, record, index){
                    console.log(record.data.name);
    开发者_开发问答                console.log(index);
                }
            }

 });
 return myCombo;
};

The combobox is inserted in an editorgridpanel. There's a renderer like this:

Ext.util.Format.comboRenderer = function(combo){
    return function(value, metadata, record){
        alert(combo.store.getCount()); //<== always 0!!
        var record = combo.findRecord(combo.valueField || combo.displayField, value);
        return record ? record.get(combo.displayField) : combo.valueNotFoundText;
    }
};

When the grid is displayed the first time, instead of have the displayField, I have : "Value not found." And I have the alert : 0 (alert(combo.store.getCount())) from the renderer. But I can see in the console that the data have been correctly loaded! Even if I try to reload the store from the renderer (combo.store.load();), I still have the alert (0)! But when I select the combo to change the value, I can see the data and when I change the value, I can see the displayFiel! I don't understand what's the problem? Since now several days, I already tried all the solutions I found...but still nothing! Any advice is welcome!

Yoong


The core of the problem is that you need to hook an listener which will execute after the grid store loaded. That listener will then convert the combo grid content to the displayField content instead of valueField. Here is my resolution to this issue.

Ext.ns("Ext.ux.renderer");
Ext.ux.renderer.ComboBoxRenderer = function(combo, grid) {
    var getValue = function(value) {
        var record = combo.findRecord(combo.valueField, value);
        return record ? record.get(combo.displayField) : value;
    };

    return function(value) {
        var s = combo.store;
        if (s.getCount() == 0 && grid) {
            s.on({
                load: {
                    single: true,
                    fn: function() {
                        grid.getView().refresh()
                    }
                }
            });
            return value
        }
        return getValue(value)
    }
};

You can use this renderer in your code like the following:

{
            header: 'Header',
            dataIndex: 'HeaderName',
            autoWidth: true,
            renderer: Ext.ux.renderer.ComboBoxRenderer(combo, grid),
            editor: combo
        }


This is a common issue. If you need a store value to display in the combo, handle the store's load event and select the appropriate value in the combo only after that. You shouldn't need a specific record just to render the combo up front.


I would recommend adding the field required from the combobox's store, to the grid's store, and change the renderer to use that field. (It does not have to be in the database) and on the afteredit event of the grid, grab that value from the combobox's store and copy it to the grid's store.

This would yield better performance.


Actually, the problem seems to be that the grid renders the combobox values BEFORE the loading of the store data. I found something here.

But when I applied the override, still the same problem... The question i: how to defer the render of the combobox, waiting for the loading of the store?

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜