-
18 May 2010 6:58 PM #1Ext User
- Join Date
- May 2010
- Location
- China, Zhejiang province, Ningbo City, a small city of 5 million people..
- Posts
- 12
- Vote Rating
- 0
EXTJS 3.2.1 - Editorgridpanel - combobox using JSON store. [SOLVED]
EXTJS 3.2.1 - Editorgridpanel - combobox using JSON store. [SOLVED]
Hi,
I have an editor grid panel with a combobox.
I cannot display the text instead of the value of the options.
After investigation and search, it seems that the problem is that the renderer to render the cell is called BEFORE the store's loading.
I already stried the patch suggested in the ComboBox FAQ and other solution but still have the same problem.
Here is a snapshot of my code for the store :
The combo:Code: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; };
And the renderer in the column model for the grid:Code: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; };
And the patch:Code:[...] ,{ id: columnName2, header: columnNameHeader2, dataIndex: columnName2, //renderer: Ext.util.Format.comboRenderer(_self.kmx_cmpappro_combo), align: _KMX_EXT_CSS_LEFT_, width: 100, sortable: false, hidden: false, resizable: true, filter: false, editor: _self.kmx_cmpappro_combo, editable: true, menuDisabled: true, hideable: true, fixe: false, } [...]
Code:// create reusable renderer for ComboBox Ext.util.Format.comboRenderer = function(combo){ return function(value){ var record = combo.findRecord(combo.valueField || combo.displayField, value); return record ? record.get(combo.displayField) : combo.valueNotFoundText; } } /** * @class Ext.grid.ComboColumn * @extends Ext.grid.Column * <p>A Column definition class which renders a ComboBox field based on the Column's configured * editor. See the {@link Ext.grid.ColumnModel#xtype xtype} config option of {@link Ext.grid.ColumnModel} * for more details.</p> */ Ext.grid.ComboColumn = Ext.extend(Ext.grid.Column, { constructor: function(cfg){ Ext.grid.ComboColumn.superclass.constructor.call(this, cfg); this.renderer = Ext.util.Format.comboRenderer(this.editor.field ? this.editor.field : this.editor); } }); // apply the custom column type to the prototype Ext.apply(Ext.grid.Column.types, { combocolumn: Ext.grid.ComboColumn }); // Form submits displayField instead of valueField: the store has to be loaded BEFORE setValue(). 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. alert('this.store.getCount() = ' + this.store.getCount()); 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; } });Last edited by kiminox; 20 May 2010 at 12:39 AM. Reason: SOLVED
-
18 May 2010 11:13 PM #2Sencha - Community Support Team
- Join Date
- Mar 2007
- Location
- The Netherlands
- Posts
- 24,251
- Vote Rating
- 41
You need to load the combobox store first and then the grid store.
(or you need to return both the id and the text in the grid store and add some extra code to keep both in sync)
-
18 May 2010 11:37 PM #3Ext User
- Join Date
- May 2010
- Location
- China, Zhejiang province, Ningbo City, a small city of 5 million people..
- Posts
- 12
- Vote Rating
- 0
Actually, the combobox store is loaded using ajax call: so, it's asynchronous.
That means I cannot control the time of loading: even if I load the store of the combobox BEFORE loading the grid, the problem will be the same.
But your second idea:"to return both the id and the text in the grid store and add some extra code to keep both in sync", what does it mean?
Where shoud I return the id and the text?
Thank you
-
18 May 2010 11:48 PM #4Sencha - Community Support Team
- Join Date
- Mar 2007
- Location
- The Netherlands
- Posts
- 24,251
- Vote Rating
- 41
Sure you can:
(and remove the autoLoads)Code:comboboxStore.load({ callback: function(){ gridStore.load(); } });
-
19 May 2010 11:42 PM #5Ext User
- Join Date
- May 2010
- Location
- China, Zhejiang province, Ningbo City, a small city of 5 million people..
- Posts
- 12
- Vote Rating
- 0
ok thank you Condor but if I have more than 1 combobox, do how to do?
This is a problem: one Ajax call for each combobox (per cell in the editor grid) but I should load the grid only when all the Ajax calls are done no?
-
20 May 2010 12:08 AM #6Ext User
- Join Date
- May 2010
- Location
- China, Zhejiang province, Ningbo City, a small city of 5 million people..
- Posts
- 12
- Vote Rating
- 0
Callback to load combobowx stores
Callback to load combobowx stores
Actually, I found a way: load the stores of the comboboxes with the callback functions...and the last callback loads the grid!
Example of my code:
Somebody has a better way to achieve that?Code:// load combobox stores BEFORE grid this.kmx_cmpappro_store.load({ callback: function() { _self.kmx_order_store.load({ callback: function() { my_grid.store.load({params:{start:0, limit:_self.kmx_pagination_page_size}}); } }); } });
It works but well, I am not really satisfied.
And if I click on the "load" button of the grid, I have to do something again ?
Thank you Condor anyway.
-
20 May 2010 12:20 AM #7Sencha - Community Support Team
- Join Date
- Mar 2007
- Location
- The Netherlands
- Posts
- 24,251
- Vote Rating
- 41
I would rewrite my server app to return all the data (comboboxes + grid) in one request.
Then you can load the comboboxes first and then the grid with the retured data.
-
20 May 2010 12:38 AM #8Ext User
- Join Date
- May 2010
- Location
- China, Zhejiang province, Ningbo City, a small city of 5 million people..
- Posts
- 12
- Vote Rating
- 0
Actually, that's what I did: I defined a reusable editor grid panel with some common buttons/actions: each child class must redefine the column model, the stores, the record, the url to save/delete...
my_editor_grid_panel.png
Fortunaly!
If somebody is interested, I can share my code with you: that's why I love OPEN SOURCE!
-
20 May 2010 12:48 AM #9Ext User
- Join Date
- May 2010
- Location
- China, Zhejiang province, Ningbo City, a small city of 5 million people..
- Posts
- 12
- Vote Rating
- 0
Actually,
There's a problem with the reloading button/action: when I modified the data, the grid auto-reloads itself (or when I click on the button refresh). Then the grid refreshs itself but without refreshing the combobox stores.
Question: how can I change the behavior of the refresh action? Do I override the load button/refresh ? How?
I found something:
But it's a quite complex no? ThanksCode:Ext.override(Ext.data.Store, { startAutoRefresh : function(interval, params, callback, refreshNow){ if(refreshNow){ this.load({params:params, callback:callback}); } if(this.autoRefreshProcId){ clearInterval(this.autoRefreshProcId); } this.autoRefreshProcId = setInterval(this.load.createDelegate(this, [{params:params, callback:callback}]), interval*1000); }, stopAutoRefresh : function(){ if(this.autoRefreshProcId){ clearInterval(this.autoRefreshProcId); } } });
-
20 May 2010 1:09 AM #10Sencha - Community Support Team
- Join Date
- Mar 2007
- Location
- The Netherlands
- Posts
- 24,251
- Vote Rating
- 41
I would recommend:
Code:var grid = new Ext.grid.EditorGridPanel({ ... viewConfig: { ... onDataChange: function(store){ combobox1.store.loadData(store.reader.jsonData); combobox2.store.loadData(store.reader.jsonData); this.constructor.prototype.onDataChange.apply(this, arguments); } } });


Reply With Quote