default value in combobox as value from store - extjs

I'm trying to get a return value of my json store to setValue in my combobox. The value of this json value is the current selected option in the database. My this.selectedCat store returns the current category value of the record where it's working in. my this.store returns all the available select options.
var fields = {
fields: ['text']
};
var notfields ={
fields:['category']
}
this.store = new GO.data.JsonStore({
url: GO.settings.modules.infoscherm.url + 'json.php',
baseParams:{
task:'selects'
},
root: 'results',
fields: fields.fields
});
this.selectedCat = new GO.data.JsonStore({
url: GO.settings.modules.infoscherm.url + 'json.php',
baseParams: {
task:'currentselectedcat',
id:'id'
},
root: 'results',
fields: notfields.fields
});
this.category = new Ext.form.ComboBox({
name: 'category',
width: 100,
store: this.store,
fieldLabel: "Categorie",
displayField:'text',
triggerAction: 'all',
editable: false,
selectOnFocus:true,
value: this.selectedCat //returns [object Object] naturally
});
Am I doing something wrong?

I think you need to start listening the "load" event of "Ext.data.JsonStore".
And the attached handler of "load" event will contain code to select any particular value by using "setValue" function of combobox object...
P.S. : Store values are made available in combobox drop down menu only if you configured the "store" config of combobox to the store object, in your case, you need to implement some logic within the handler of "load" event.

Related

Extjs Combo - How to load value to combo using GetForm().load

I have a combo box inside a form like:
xtype: 'combo',
id: 'example',
name: 'ax',
triggerAction: 'all',
forceSelection: true,
editable: false,
allowBlank: false,
fieldLabel: 'example',
mode: 'remote',
displayField:'name',
valueField: 'id',
store: Ext.create('Ext.data.Store', {
fields: [
{name: 'id'},
{name: 'name'}
],
//autoLoad: false,
proxy: {
type: 'ajax',
url: 'example.php',
reader: {
type: 'json',
root: 'rows'
}
}
}
})
I don't want that auto load because that's slow when i start.
But i want set a value to combo box when i click edit button and load value to combo
this.down('form').getForm().load({
url: 'load.php',
success:function(){
}
});
data from load.php like (name of combe is ax)
{ success:true , data : { ax: '{"id":"0","name":"defaults"}' } }
But that's not working. How can i do that thanks.
p/s: If i have autoLoad : true and data is { success:true , data : { ax: '0' } } that's work well. But that's slow when i start.
What you want to do is make sure the combo is loaded before you try to set it's value.
You could check if the combo's store has any data in it:
if(combo.getStore().getCount() > 0)
{
//the store has data so it must be loaded, you can set the combo's value
//doing a form.load will have the desired effect
}
else
{
//the store isn't loaded yet! You can't set the combo's value
//form.load will not set the value of the combo
}
If it does, you can just set the value. But more likely however it will not have been loaded.
You could also do something like this
//in the controller's init block
this.control({
"#myEditButton" : {click: this.loadForm}
});
//a function in your controller
loadForm: function(button)
{
var combo; //get your combo somehow, either via references or via the button
combo.getStore().load({
scope: this,
callback:
function(records, operation, success)
{
if(success)
{
//load your form here
}
}
});
}
I know that might seem like a lot of code, but it's the only way to know for sure if the combo was loaded. If it is not, you cannot set it's value.
A third option would just be to explicitly load the store before you open your view.

How to dynamically assign value to the store in ExtJS Itemselector?

I have to fill values in the right multiselect box in an itemselector. First i need to keep it blank and then on selection of an item in the combo box above it, i have to fill values accordingly. I have tried this and its crashing at the moment and nothing seems wrong. Here is the code snippet:
var userList = GetUserList();
var aoiList = GetAOIList();
var userAOIs = "";
var selectedUser="";
var userStore = new Ext.data.ArrayStore({
fields: ['user'],
data: userList
});
var aoiStore = new Ext.data.ArrayStore({
fields: ['aoiList'],
data: aoiList
});
var userAOIStore = new Ext.data.ArrayStore({
fields: ['userAOIs'],
data: userAOIs
});
var aafp = new Ext.FormPanel({
width : 350,
frame : true,
autoHeight : true,
bodyStyle : 'padding: 2px 5px 0 2px;',
labelWidth : 100,
defaults : {
anchor : '95%',
allowBlank : false,
msgTarget : 'under'
},
items : [ {
xtype : 'combo',
fieldLabel : 'Choose User',
emptyText: "Select User...",
id : 'userId',
name : 'user',
multiSelect: false,
store: userStore,
displayField: 'user',
mode: 'local',
editable: false,
typeAhead: true,
triggerAction: 'all',
listeners:{select:{fn:function(combo, value) {
selectedUser = value.get('user');
userAOIs = myAOIs(selectedUser);
userAOIStore = new Ext.data.ArrayStore({
fields: ['userAOIs'],
data: userAOIs});
aafp.getForm().findField("itemselector").reset();
}}
},
value : selectedUser
},{
xtype: 'itemselector',
name: 'itemselector',
fieldLabel: 'AOISelector',
imagePath: 'ext-3.4.0/examples/ux/images/',
drawUpIcon:false,
drawDownIcon:false,
drawTopIcon:false,
drawBotIcon:false,
multiselects: [{
width: 250,
height: 200,
store: aoiStore,
displayField: 'aoiList'
},{
width: 250,
height: 200,
store: userAOIStore,
displayField: 'userAOIs',
valueField: 'userAOIs'
}]
}]
Initially i doubted the "aafp.getForm().findField("itemselector").reset()" call and thought that there might be some other function to dynamically reload the elements in the form, instead of reset which might be used to reset/erase the data in the fields but reset is reloading the contents.
Please provide your inputs how this could be achieved?
Thanks
You can try this:
1) Create the stores.
2) Add the stores to the components
3) When the listener 'selected' is fired get the component who store you would like to dynamical add to and create a new record and add it to the store.
EDIT:
Try something like this (its what I think you want) note the code isn't exact since I'm not sure what exactly you want to do but it should give you an idea of what you need to do.
listeners:{select:{fn:function(combo, value) {
var selectedUser = value.get('user');
var record = Ext.data.Record.create([
'user' : selectedUser
]);
var cmp = Ext.getCmp('compId');//Get the comp that contains the store you want to add to put the cmp id here to look it up
cmp.store.removeAll();//Clear the store
cmp.store.add([record]);//Add the new record into the store
}, this}
Thanks for your inputs, it was helpful.
I found the problem: I was creating a new instance of Ext.data.ArrayStore but the view was linked to the previous instance.
So i used the previous instance, removed everything from it and added new records, jus as theboulderer suggested. But I found that we don't have to catch the handle of itemselector store, it was automatically updated with the modified store.
sample:
var tempUserAOIStore = new Ext.data.ArrayStore({
fields: ['userAOIs'],
data: [['8'], ['9']]
});
userAOIStore.removeAll();
userAOIStore.add(tempUserAOIStore.getAt(0));
userAOIStore.add(tempUserAOIStore.getAt(1));
Now this facility in ArrayStore is also a problem for me as the stores are so tightly binded that if i want to keep the original in some temp store, it is also modified. i.e.
if i do :
B = A;
Itemselector: store = A
A.remove(some records)
I find that B is also modified as A is modified. I am answering here so guess have to post this as a seperate question

Dynamically changing the DataStore of a ComboBox

I have a combo box which populates its values based on the selection of another combobox.
I have seen examples where the params in the underlying store are changed based on the selection, but what I want to achieve is to change the store itself of the second combo based on the selection on the first combo. This is my code, but it doesn't work. Can someone please help?
{
xtype: 'combo',
id: 'leads_filter_by',
width: 100,
mode: 'local',
store: ['Status','Source'],
//typeAhead: true,
triggerAction: 'all',
selectOnFocus:true,
typeAhead: false,
editable: false,
value:'Status',
listeners:{
'select': function(combo,value,index){
var filter_to_select = Ext.getCmp('cmbLeadsFilter');
var container = filter_to_select.container;
if (index == 0){
filter_to_select.store=leadStatusStore;
filter_to_select.displayField='leadStatusName';
filter_to_select.valueField='leadStatusId';
} else if(index==1) {
filter_to_select.store=leadSourceStore;
filter_to_select.displayField='leadSourceName';
filter_to_select.valueField='leadSourceId';
}
}
}
},
{
xtype: 'combo',
id: 'cmbLeadsFilter',
width:100,
store: leadStatusStore,
displayField: 'leadStatusName',
valueField: 'leadStatusId',
mode: 'local',
triggerAction: 'all',
selectOnFocus:true,
typeAhead: false,
editable: false
},
That is not how its designed to work!! When you set a store in the config, you are binding a store to the combo. You don't change the store, instead you are supposed to change the data when required.
The right way of doing it would be to load the store with correct data from the server. To fetch data, you can pass params that will help the server side code get the set of options you need to load.
You will not want to change the store being used... Simply put, the store is bound to the control as it is instantiated. You can, however, change the URL, and params/baseParams used in any additional POST requests.
Using these params, you can code your service to return different sets of data in your combo box's store.
For the proposed problem you can try below solution :
Use below "listener" snippet for the first "leads_filter_by" combo. It will handle the dynamic store binding / changing for the second combobox.
listeners:{
'select': function(combo,value,index){
var filter_to_select = Ext.getCmp('cmbLeadsFilter');
var container = filter_to_select.container;
if (index == 0){
//filter_to_select.store=leadStatusStore;
filter_to_select.bindStore(leadStatusStore);
filter_to_select.displayField='leadStatusName';
filter_to_select.valueField='leadStatusId';
} else if(index==1) {
//filter_to_select.store=leadSourceStore;
filter_to_select.bindStore(leadSourceStore);
filter_to_select.displayField='leadSourceName';
filter_to_select.valueField='leadSourceId';
}
}
}
Hope this solution will help you.
Thanks & Regards.
I had a similar problem. The second combobox would load the store and display the values, but when I would select a value, it would not actually select. I would click the list item and the combobox value would remain blank.
My research also suggested that it was not recommended to change the store and field mappings on a combobox after initialization so here was my solution:
Create a container in the view that would hold the combobox to give me a reference point to add it back later
Grab a copy of the initial config off of the combobox ( this lets me set my config declaritively in the view and not hard code it into my replace function ... in case I want to add other config properties later)
Apply new store, valueField and displayField to that config
Destroy old combobox
Create new combobox with modified config
Using my reference from step 1, add the new combobox
view:
items: [{
xtype: 'combobox',
name: 'type',
allowBlank: false,
listeners: [{change: 'onTypeCombo'}],
reference: 'typeCombo'
}, { // see controller onTypeCombo for reason this container is necessary.
xtype: 'container',
reference: 'valueComboContainer',
items: [{
xtype: 'combobox',
name: 'value',
allowBlank: false,
forceSelection: true,
reference: 'valueCombo'
}]
}, {
xtype: 'button',
text: 'X',
tooltip: 'Remove this filter',
handler: 'onDeleteButton'
}]
controller:
replaceValueComboBox: function() {
var me = this;
var typeComboSelection = me.lookupReference('typeCombo').selection;
var valueStore = Ext.getStore(typeComboSelection.get('valueStore'));
var config = me.lookupReference('valueCombo').getInitialConfig();
/* These are things that get added along the way that we may also want to purge, but no problems now:
delete config.$initParent;
delete config.childEls;
delete config.publishes;
delete config.triggers;
delete config.twoWayBindable;
*/
config.store = valueStore;
config.valueField = typeComboSelection.get('valueField');
config.displayField = typeComboSelection.get('displayField');
me.lookupReference('valueCombo').destroy();
var vc = Ext.create('Ext.form.field.ComboBox', config);
me.lookupReference('valueComboContainer').add(vc);
},

ExtJS : How to set combobox id?

I have a little problem. At my application Im always building two linked combobox - country and towns(then country are selected - towns began to load). So i thinked - mbe write a constructor and minimized my code? Ok i did it. But i got a problem: i have 2-3 couple of this linked comboboxes on page and when i selected at second combo country, the data (towns) loads at first combo, because it has the same id. Ok - now im trying take a param id to constructor and it didnt work. How set id of combobox then i create an object?
Country combo
comboCountryClass = Ext.extend(Ext.form.ComboBox, {
fieldLabel: 'country',
anchor: '95%',
lazyRender:true,
store:new Ext.data.Store({
proxy: new Ext.data.HttpProxy(
{url: '../lib/getRFB.php?rfb_type=countrys',
method: 'GET'}
),
reader: countryReader,
autoLoad: true
}),
displayField:'country_name',
valueField:'country_id',
triggerAction:'all',
mode:'local',
listeners:{
select:{
fn:function(combo, value) {
var modelCmp = Ext.getCmp(this.town_name_id);
alert(this.town_name_id);
modelCmp.setValue('');
modelCmp.getStore().proxy.setUrl('../lib/getRFB.php');
modelCmp.store.reload({
params: { 'country_id': this.getValue(),rfb_type: 'towns' }
});
}
}
},
hiddenName:'country_id',
initComponent: function() {comboCountryClass.superclass.initComponent.call(this);}})
And town combo
comboTownClass = Ext.extend(Ext.form.ComboBox, {
fieldLabel:'town',
displayField:'town_name',
valueField:'town_id',
hiddenName:'town_id',
anchor: '95%',
id:this.town_name_id || 'youuuu',
store: new Ext.data.Store({
proxy: new Ext.data.HttpProxy(
{url: 'lib/handlers/orgHandler.php?action=read&towns=true',
method: 'GET'}
),
reader: townReader
}),
triggerAction:'all',
mode:'local',
initComponent: function() {comboTownClass.superclass.initComponent.call(this);}})
new comboTownClass({town_name_id:'townFormSearch'})
new comboCountryClass({town_name_id:'townFormSearch'})
You can set the id of the component by doing the following:
new comboTownClass({id:'townComboId'});
new comboCountryClass({id:'countryComboId'});
You can specify a default id, and when you pass an id in the config param it will overwrite the default value.
Although I agree with #Upper Stage you should try to limit the amount of hard-coded id values you have in the form - you can instead grab form elements using the form name instead.
I live by the rule: "never use hardcoded IDs." You can retrieve a unique ID from Ext JS using
Ext.id( null, 'someTextString' )
You will incur more bookkeeping when you use unique IDs, but you will not run into the problem about which you write above.
Sometimes I store unique IDs locally in an object and then reference that instance variable where necessary.
this.idForCombo = Ext.id( null, 'someTextString' );
var myCmp = new SomeConstructor({
id: this.idForCombo,
...more stuff });
myCombobox.id = yourId;

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?

Resources