Could you please tell somebody how prevent fires select event on combobox when focus leave ?
I had the same issue in extjs 6.5.2 modern. I was using a combobox with queryMode: 'remote', forceSelection: true, a custom itemTpl and i was choosing an item using the select event. #Jzf's solution didn't worked for me (i used the change event too) so i had to suspend the select event on focusleave and resume it on focusenter.
That's not a very clean workaround but it does the job for my case.
Here is the full code for my combobox:
{
xtype: 'combobox',
store: Ext.create('demo.store.search.SearchComboStore'),
valueField: 'id',
displayField: 'name',
queryMode: 'remote',
queryParam: 'name',
triggerAction: 'all',
allQuery: '',
minChars: 1,
forceSelection: true,
matchFieldWidth: false,
//[modern] added floated picker config here in order to set the minWidth property for the floated picker
floatedPicker: {
minWidth: (Ext.getBody().getWidth() / 2)
},
itemTpl:
'<div class="ucResultsTable" style="width:' + (Ext.getBody().getWidth() / 2) + 'px">' +
'<div class="ucResultsTableCell" style="width:15%"><b>{value1}</b></div>' +
'<div class="ucResultsTableCell" style="width:15%">{value2}</div>' +
'<div class="ucResultsTableCell" style="width:15%">{value3}</div>' +
'<div class="ucResultsTableCell" style="width:15%">{value4}</div>' +
'<div class="ucResultsTableCell" style="width:15%">{value5}</div>' +
'</div>',
listeners: {
select: function (comboBox, records, eOpts) {
var container = comboBox.up('app-container-panel');
container.fireEvent('selectComboItem', container, records.data);
},
//<Workaround>
//blur/focusleave is firing select event
//and changes the record selection
focusleave: function (comboBox) {
comboBox.suspendEvent('select');
},
focusenter: function (comboBox) {
comboBox.resumeEvent('select');
}
//</Workaround>
}
}
The problem occurs because the combo forces the selection, even when the user hasn't actually selected another value.
There are a couple of ways to workaround this issue.
Use the select listener without forceSelection
Use the change listener with forceSelection
Both ways, the user will have to choose an item from the combo list (which is, probably, why you used the forceSelection config in the first place).
Test the workaround in fiddle
THis is a bug
Correspond theme on Sencha Forum
Related
So I'm trying to create an 'abnormal' combobox using ExtJs 4 and I'm running into a slight issue which I can't figure out how to resolve. I got the basics down with the code that follows. As of right now I am able to get the dropdown to show all the addresses in a proper format and when I click on the proper address it properly shows the 'Street1' value in the input.
Here is what I'm stuck on:
I'm trying to add an initial item to the combobox that basically says something like 'Add New Address' that the user can select. (I'm planning on having this open a modal where the user can input a new address, save it and then have it be displayed back in the combobox, but all of that should be fairly simple) I can't seem to figure out a way of adding just a simple 'Add New Address' and then tracking the value to see if that value is returned to know to make the modal appear or not. I don't want to add it to the store as (I assume) that will add an item in the database and I'd prefer that not happen for the 'Add New Address'.
Any thoughts on how to get that to work? From below you can see that LocationStore is my store and that the general address components apply.
Thank you in advance.
ComboBox Code:
{
xtype: 'combobox',
anchor: '100%',
listConfig: {
emptyText: 'Add New Address - Empty Text',
itemTpl: '<tpl if="Name">{Name}<br /></tpl>'+'<tpl if="Street1">{Street1}<br /></tpl>'+'<tpl if="Street2">{Street2}<br /></tpl>'+'{City}, {StateOrProvince} {PostalCode}'
},
emptyText: 'Add New Location - tester',
fieldLabel: 'Street 1',
name: 'Street1',
allowBlank: false,
blankText: 'Street 1 Required',
displayField: 'Street1',
forceSelection: true,
store: 'LocationStore',
typeAhead: true,
valueField: 'Street1',
valueNotFoundText: 'Add New Location'
},
Thanks to those who pointed me to the right place in the doc, I finally found it!
I managed to achieve what you want by using the tpl, unfortunately I could not find a way to make the keyboard navigation work for the added item. I've looked at the code of Ext.view.BoundListKeyNav, but didn't find any easy solution...
The key was to use tpl instead of itemTpl, and add the markup for the extra item before the for loop:
listConfig: {
tpl: '<div class="my-boundlist-item-menu">Add New Address</div>'
+ '<tpl for=".">'
+ '<div class="x-boundlist-item">' + itemTpl + '</div></tpl>'
,listeners: {
el: {
delegate: '.my-boundlist-item-menu'
,click: function() {
alert('Go go go!');
}
}
}
}
The rest of the code in on jsFiddle.
#rixo see the comments on sencha api:
Config: Ext.form.field.ComboBoxView
ADD VALUE:
Maybe we can use Sencha merge object function...
To put 'add new location' value at the store top:
var newLocation = { 'Street' : 'Add New Location' };
var dataMerged = Ext.Object.merge(newLocation,myStore.getRange());
myStore.loadData(dataMerged);
SORT:
add name config param to your combobox
On controller: (2 ways)
'nameComboView combobox[name=combo]' : {
select : this.function1, // <-- when you select a item
change : this.funciton2 // <-- when the item select are changing
}
Now, on function, compare the value to open modal window or not.
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.
I'm looking for EXTJS4 combobox control which allows selecting multiple items via checkboxes inside.
Actually I need this control http://lovcombo.extjs.eu/ but it is implemented for ExtJs3. I tried to convert it to ExtJs4 but the task is not trivial actually.
Could you suggest similar component for ExtJs4. Or maybe you could point me to some tutorial or example - how to do such things?
Multiselect combo with checkbox in ExtJS4.0 can be achieved with addition few lines of code.
Basically you need to make use of the existing css class which get applied during selection and deselection of an item and pushing an image (checkbox image) at that time accordingly.
"x-boundlist-item" and "x-boundlist-selected" are the classes taken from ext-all.css.
<style>
.x-boundlist-item img.chkCombo {
background: transparent url(/lib/extjs-4.1.0/resources/themes/images/default/menu/unchecked.gif);
}
.x-boundlist-selected img.chkCombo{
background: transparent url(/lib/extjs-4.1.0/resources/themes/images/default/menu/checked.gif);
}
</style>
<head>
Ext.create('Ext.form.ComboBox', {
id: 'BCCAddress',
name: 'BCCAddress',
maxHeight: 150,
width: 210,
multiSelect: true,
emptyText : "Select Bcc email addresses",
renderTo: 'extBCCAddress',
store: myArrayStore,
displayField: 'fieldName',
valueField: 'fieldName',
forceSelection: true,
editable: false,
mode: 'local',
triggerAction: 'all',
listConfig : {
getInnerTpl : function() {
return '<div class="x-combo-list-item"><img src="' + Ext.BLANK_IMAGE_URL + '" class="chkCombo-default-icon chkCombo" /> {fieldName} </div>';
}
}
});
[below is an image of this custom component]
use this: http://www.sencha.com/forum/showthread.php?134751-Ext.ux.form.field.BoxSelect-Intuitive-Multi-Select-ComboBox
or this: http://www.sencha.com/forum/showthread.php?132328-CLOSED-ComboBox-using-Grid-instead-of-BoundList
-- use grid with checkboxselectmodel in combox
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);
},
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);