extjs4 combobox trunks value - combobox

I have a comboBox within a form, the valueField is the ObjectId field of a document in mongodb, it displays the proper value of the fields in the comboBox, but it returns just a part of the value with getValue, getRawValue returns the value of the displayField.
This is the code of the comboBox:
{
xtype: 'combo',
fieldLabel:'Firm',
store:Ext.data.StoreManager.lookup('bbCompaniesStore'),
displayField: 'firm',
valueField: '_id',
name: 'country',
labelAlign: 'top',
cls: 'field-margin',
flex: 1
}
This is how I get the value from the form:
var nomeField = formPanel.items.get(0).items.get(0);
var firmField = formPanel.items.get(0).items.get(1);
var noteField = formPanel.items.get(0).items.get(2);
var contact = Ext.ModelManager.create({nome: nomeField.getValue(), note: noteField.getValue(),'firm_id':firmField.getValue()}, 'Contact');
It works but it trunks the value of _id, I checked with firebug, the server sends the rigth data,I think that extjs does some kind of normalization, before I solved using getRawValue, but with combobox it returns the displayField. I do not know how to fix this problem.

Related

Not able to select item by typing inside combobox

This is my second time I am posting the same question as did not get answer till now.
I have a combobox and following is the store (ExtJs 2.3)
Combo Store:
Assignments
Meetings
Salary
I am filtering the combo on key up so that 'Salary' item wont be diaplyed int he list and it works fine.
But as the combobox item can also be selected by typing iside combobox, I have written following code on keyUp and beforeQuery of the combo.
keyup: function () {
combo2.selectedIndex = -1;
combo2.store.clearFilter();
combo2.store.filterBy(function (record) {
return record.get('text') != 'Salary';
});
}
beforequery: function (queryEvent) {
var combo1Val = combo.value; // Give the selected value correctly
if (combo1Val == 'Student' && combo2.store.isFiltered())
{
queryEvent.combo.expand();
queryEvent.combo.onLoad();
return false;
}
return true;
}
This filters out the 'Salary' option successfully, but now I am not able to select any option by typing the inside combobox as before i.e. now if I type 'As', it is not selecting 'Assignment' option anymore. What I am doing wrong here?
Have you tried using typeAhead?
something like this--
{
xtype: 'combobox',
name: 'address',
id: 'addressId',
store: Ext.create('myStore'),
valueField: 'fullAddress',
displayField: 'name',
minChars: 2,
typeAheadDelay: 100,
typeAhead: true,
emptyText: 'Select Address',
listEmptyText: 'error loading list!',
width: 300
}

ExtJS How to force render on grid row after combo editor select

I have in my ExtJS 4.2.1 Application a grid with the following editable column:
text: 'Location',
dataIndex: 'LocationId',
width: 140,
renderer: function(value) {
var record = me.store.findRecord('LocationId', value);
return record.get('Description');
},
editor: {
xtype: 'combobox',
typeAhead: true,
triggerAction: 'all',
store: Ext.create('App.store.catalog.Location', {
autoLoad: true
}),
displayField: 'Description',
valueField: 'LocationId',
listConfig: {
width: 250,
loadingText: 'Searching...',
// Custom rendering template for each item
getInnerTpl: function() {
return '<b>{Code}</b><br/>(<span style="font-size:0.8em;">{Description}</span>)';
}
}
}
The combo has a renderer to display the Description of the LocationId selected.
Then, my grid has the feature 'Ext.grid.plugin.CellEditing' so I can edit just that column cell.
The problem that I have is when I press the "Update" button, the combo display value returns to the original it used to have, even if the LocationId in the record has the right value.
This is my code that gets fired when the user press the "Update" button.
me.rowEditing = Ext.create('Ext.grid.plugin.RowEditing', {
clicksToMoveEditor: 1,
autoCancel: false,
listeners: {
edit: function(editor, e) {
var record = e.record;
me.setLoading('Updating...');
App.util.Ajax.request({
noMask: true,
url: '/api/catalog/UpdateEmployeeLocation',
jsonData: record.getData(),
success: function(response, opts) {
var obj = Ext.decode(response.responseText);
if (obj.success) {
// commit changes (no save just clear the dirty icon)
me.getStore().commitChanges();
}
},
callback: function() {
me.setLoading(false);
}
});
}
}
});
The record is saved correctly in my database but the combo display value is not updated with the description that corresponds to the LocationId. If I reload the store from server again then It shows correctly.
So, there is something wrong with the renderer in my column that is not updating the value after I update my record.
Any clue on how to get around this?
Thanks.
You are setting dataIndex as 'LocationId' but no where you are changing the 'LocationId', you are just changing description and updating it in rendered method. Since there no change in 'LocationId', store doesn't consider it as dirty field and hence rendered function is not getting called. One quick and dirty way could be instead of using 'LocationId', create another field in the model say 'LocationIdchangeTraker'. Use 'LocationIdchangeTraker' instead of 'LocationId' in data index. It doesn't not effect your view because you are changing the value in reneerer function. Now whenever you update the function change the value of 'LocationIdchangeTraker' as shown below.
record.set('LocationIdchangeTraker',Ext.getId());

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.

extjs 3.4 editable grid: how to separate displayField and ValueField in column

I'm trying to make something that looks like: http://dev.sencha.com/deploy/ext-3.4.0/examples/grid/edit-grid.html
But I want to change Light column:
I want it to contain ids instead of actual values.
I can force combobox to separate values from presentation but not the actual column value (in fact I don't know where to store id-value mapping for column (not just for the editor)):
new Ext.grid.EditorGridPanel({
...
store: new Ext.data.Store ({
...
fields: [
'MagicId',
...
]
})
columns: [
{
header: 'Magic',
dataIndex: 'MagicId',
editor: new Ext.form.ComboBox({
store: new Ext.data.Store({
...
fields: ['id', 'title']}),
valueField: 'id',
displayField: 'title',
editable: 'false'
})
},
...
]
When I select "Magic title" in combobox I get MagicId in my grid anyway. I understand why it's happening but can't make it work the way I need it to work...
I tried to replace all unnecessary code with ... to help you reading.
Thank you for your attention.
Keep the ID field in your grid/store, then use the "renderer" property to display something else. ID-text mapping could be stored in an array or an object:
{
header: 'Magic',
dataIndex: 'MagicId',
renderer: function(value) {
return magicIdValueArray[value];
}
...
}
EDIT:
Since you already have the ID-value mapping in the combo store, I would use that store to fetch the value (it needs to be declared outside the combobox).
renderer: function(value) {
var record = comboStore.findRecord('id', value);
return record.title;
}

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);
},

Resources