EXTJS combobox default value after form layout - combobox

My combobox's data is loaded after the form layout.
var villeStore = new Ext.data.ArrayStore({
fields: [{name:'idVille'}
,{name: 'ville'}]
});
var villeInput = new Ext.form.ComboBox({
fieldLabel: 'Ville',
store: villeStore,
valueField:'idVille',
displayField:'ville',
typeAhead: true,
mode: 'local',
triggerAction: 'all',
emptyText:'Ville',
width:100,
id:'villeInput'
});
The problem is that I need to display the last of the store, but even have the valueField, because when I click on a button, this is what I send to server
I did this, but it don't work, it show the last store value, but don't have the valueField
villeInput.store.on('load',function(store) {
villeInput.setValue(store.getAt(villeInput.store.getCount()-1).get('ville'));
});

The problem is that you need to set the value of the combo using the valueField (which is idVille) instead of the displayField:
villeInput.store.on('load',function(store) {
villeInput.setValue(store.getAt(villeInput.store.getCount()-1).get('idVille'));
});

Try this:
villeInput.store.on("load", function(store) {
villeInput.setValue(ActualidVille, false);
}, this);

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.

remote combobox gives AJAX call for the first time even if it is cascaded

Team,
I am having strange problem.
I am having two combo-boxes and I want to cascade one of them using the value of other.
So on select event of one combo-box I am getting another combo box and loading that store.
But what I have observed is the below case.
User selects first combo box value for very first time so store is loaded for second combo box.
When user selects second combo-box for very first time then AJAX call is made don't know why ?
Once again if user selects combo-box one then store is loaded for combo-box second
When user selects second combo-box once again AJAX call is not made (Why AJAX call is made for the first time)
I am not able to understand during step 2 why AJAX call is made for second combo as it is already loaded in step 1.
Code details
xtype: 'combo',id='firstcombo', name: 'DEFAULT_VALUE' ,minChars:2, value: decodeHtmlContent('') ,width:200 ,listWidth:500, resizable: true,
valueField : 'id', displayField: 'id', pageSize: 15,forceSelection:true, enableKeyEvents: true,
store: new Ext.data.Store({reader: new Ext.data.CFQueryReader({id: 'NAME',
fields:[{name:'id', mapping:'id'}]}),
fields: [{name:'id', mapping:'id'}],
url:'server/ajax/Params'
}
}),
listeners : {
select:function(combo, record, index) {
this.setRawValue(decodeHtmlContent(record.get('id')));
cascadeFields();
}
xtype: 'combo',id='secondcombo', name: 'DEFAULT_VALUE' ,minChars:2, value: decodeHtmlContent('') ,width:200 ,listWidth:500, resizable: true,
valueField : 'id', displayField: 'id', pageSize: 15,forceSelection:true, enableKeyEvents: true,
store: new Ext.data.Store({reader: new Ext.data.CFQueryReader({id: 'NAME',
fields:[{name:'id', mapping:'id'}]}),
fields: [{name:'id', mapping:'id'}],
url:'server/ajax/Params',
baseParam:{valuefirst:''}
},
listeners: {
beforeload: function(store, options) {
var value = Ext.getCmp('fistcombo').value;
Ext.apply(options.params, {
valuefirst:value
});
},
}),
listeners : {
select:function(combo, record, index) {
this.setRawValue(decodeHtmlContent(record.get('id')));
}
function cascadeFields()
{
var combo = Ext.getCmp('secondcombo');
if(combo.store)
{
var store = combo.store;
combo.setDisabled(true);
combo.clearValue('');
combo.store.removeAll();
combo.store.load();
combo.setDisabled(false);
}
}
You should specify no autoload on the stores:
autoload: false
And on the combo boxes, you should set the querymode to local:
queryMode: 'local'
Edit: You might want autoload on the first combo store though.

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 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