ExtJS 5.0 - Changing combobox displayField at runtime - extjs

I have data with two possible display fields: en and fr. Depending on the locale of the user, I'd like to use one or the other as displayField in the combobox, ideally dynamically.
Among many other approaches, I have tried setting displayField to 'en' or 'fr' in initComponent of the combobox, even before this.callParent but it doesn't work right. It might show the correct values in the dropdown, but it won't show it as a selection or sometimes won't even let you select values.
// The sample data
var digits = [
{id: 1, en: 'one', fr: 'un'},
{id: 2, en: 'two', fr: 'deux'},
{id: 3, en: 'three', fr: 'trois'},
{id: 4, en: 'four', fr: 'quatre'},
{id: 5, en: 'five', fr: 'cinq'},
{id: 6, en: 'six', fr: 'six'},
{id: 7, en: 'seven', fr: 'sept'},
{id: 8, en: 'eight', fr: 'huit'},
{id: 9, en: 'nine', fr: 'neuf'},
{id: 10, en: 'zero', fr: 'zéro'}
];
// Define the model for a digit
Ext.define('Digit', {
extend: 'Ext.data.Model',
fields: [
{type: 'integer', name: 'id'},
{type: 'string', name: 'en'},
{type: 'string', name: 'fr'}
]
});
// The data store holding the digits
var store = Ext.create('Ext.data.Store', {
model: 'Digit',
data: digits
});
// Simple form
Ext.create('Ext.form.Panel', {
title: 'Digits',
bodyPadding: 10,
width: 300,
layout: 'anchor',
items: [{
xtype: 'combobox',
fieldLabel: 'Select a digit',
valueField: 'id',
displayField: 'en',
store: store,
queryMode: 'local',
typeAhead: true/*,
// This code will prevent the combobox from working properly.
// Even commenting out this.displayField = 'fr'; mucks it up!
initComponent:
function () {
this.displayField = 'fr';
this.callParent(arguments);
}*/
}],
renderTo: Ext.getBody()
});
I've looked through the component and it appears even in initComponent before calling this.callParent that the combobox is completely initialized.
Is there some other way to set displayField of a combobox at runtime and have it work correctly?

Try this (tested in a fiddle with ExtJS 5.0.0 and 5.0.1):
Ext.create('Ext.form.Panel', {
title: 'Digits',
bodyPadding: 10,
width: 300,
layout: 'anchor',
items: [{
xtype: 'combobox',
fieldLabel: 'Select a digit',
valueField: 'id',
displayField: 'en',
store: store,
queryMode: 'local',
typeAhead: true,
initComponent: function () {
me = this;
me.displayField = 'fr';
this.callParent(arguments);
}
}],
renderTo: Ext.getBody()
});
With ExtJS5.1 this would work fine:
Ext.create('Ext.form.Panel', {
title : 'Digits',
bodyPadding: 10,
width : 300,
layout : 'anchor',
items: [{
xtype : 'combobox',
fieldLabel : 'Select a digit',
valueField : 'id',
displayField: 'en',
store : store,
queryMode : 'local',
typeAhead : true,
listeners: {
render: function(combobox) {
combobox.setDisplayField('fr');
}
}
}],
renderTo: Ext.getBody()
});

Related

Ext Js Combobox displayTpl is shown twice

I'm trien to populate a ExtJS 7.3.1 combobox with key/value from an array.
Then I need to display both (Key and Value) on the combobox and the dropdown like this:
var test_store = new Ext.data.SimpleStore({fields : ['value','text'],data : []});
var testArr = [
['test 1', '1'],
['test 2', '2'],
['test 3', '3'],
['test 4', '4'],
]
var combo = Ext.getCmp('test');
test_store = new Ext.data.SimpleStore({
fields: ['value', 'text'],
data: testArr,
});
Ext.create({
xtype: 'formpanel',
renderTo: document.body,
items: [{
xtype: 'combobox',
id: 'test',
name: 'test',
label: 'test',
store: test_store,
displayField: 'text',
valueField: 'value',
queryMode: 'local',
editable: false,
displayTpl: '{value} - {text}',
itemTpl: '<div data-qalign="b-t" data-qanchor="true" data-qtip="{text}">{value} - {text} </div>',
autocomplete: false,
}]
});
But when I unfocus the combobox after I have selected a new value, it will show the displayTpl twice, am I doing something wrong or do I need to report a bug?
fiddle:
https://fiddle.sencha.com/#view/editor&fiddle/3c6i
I really would only override displayTpl or itemTpl if you know what you're doing. In the case of this, I'd say create a separate field and do the conversion there. Like this
var test_store = new Ext.data.SimpleStore({fields : ['value','text'],data : []});
var testArr = [
['test 1', '1'],
['test 2', '2'],
['test 3', '3'],
['test 4', '4'],
]
var combo = Ext.getCmp('test');
test_store = new Ext.data.SimpleStore({
fields: ['value', 'text', {
name: 'display',
type: 'string',
depends: ['value', 'text'],
convert: function(value, record) {
return `${record.get('value')} - ${record.get('text')}`
}
}],
data: testArr,
});
Ext.create({
xtype: 'formpanel',
renderTo: document.body,
items: [{
xtype: 'combobox',
id: 'test',
name: 'test',
label: 'test',
store: test_store,
displayField: 'display',
valueField: 'value',
queryMode: 'local',
autocomplete: false,
anyMatch: true,
forceSelection: true
}]
});

Blank value in Grid with combobox when force select is true

I got a combocox in editor grid. When entering values I have to validate so I used property forceSelection : true . But turning on force selection raise another problem as the combo value is blank when the combo box loss focus as below attached image.
Sample code:
var employeeType = [{
'typeid': 1,
'typename': 'Contractor'
}, {
'typeid': 1,
'typename': 'Regular'
}];
var employeeTypeStore = Ext.create('Ext.data.Store', {
fields: ['typeid', 'typename'],
data: employeeType
});
Ext.define('Employees', {
extend: 'Ext.data.Model',
fields: [{
name: 'emptype',
type: 'string'
}, {
name: 'name',
type: 'string'
},
]
});
var empStore = Ext.create('Ext.data.Store', {
model: 'Employees',
data: [{
'emptype': 'Regular',
'name': 'John Doe'
},{
'emptype': 'Regular',
'name': 'Ricky'
},{
'emptype': 'Regular',
'name': 'Mason'
}]
});
var grid = Ext.create('Ext.grid.Panel', {
renderTo: Ext.getBody(),
store: empStore,
width: 1000,
height: 500,
title: 'Employees',
columns: [{
text: 'Employee Type',
dataIndex: 'emptype',
editor: {
xtype: 'combobox',
queryMode: 'local',
store: employeeTypeStore,
displayField: 'typename',
valueField: 'typeid',
forceSelection : true
}
}, {
text: 'Employee Name',
dataIndex: 'name'
}],
plugins: {
ptype: 'cellediting',
clicksToEdit: 1
}
});
If the value is false then I need to show the last correct value.
Its the Expected behavior.
Setting forceSelection: true will restrict the user to select the value which is present in the list only. So if you loose the focus without selecting any item it will gonna blank.
You can use typeAhead: true to populate and autoselect the remainder of the text being typed if it matches a known value.

Combobox inside grid doesn't show data after rendering

I have a grid that has combobox on one column. Data loads fine on the grid. But when I double click on one row to enable edit, the combobox doesn't show the data. (Please see the screenshot below) The highlighted part should show '1st Label'. But when I start to edit, it shows up like in the 2nd row with '2nd Label'.
I tried my code on 4.1 and it works fine. It seems 4.2.2 doesn't like combobox inside grid. Any help is really appreciated
This is my sample code. Please try it on Sencha's Code Editor to see both on 4.2.2 and 4.1.0
Ext.define('GridModel', {
extend: 'Ext.data.Model',
fields: [{
name: 'Id',
type: 'int'
}, {
name: 'Value',
type: 'int'
}]
});
Ext.define('ComboModel', {
extend: 'Ext.data.Model',
fields: [{
name: 'ComboId',
type: 'int'
}, {
name: 'Label',
type: 'string'
}],
idProperty: 'Order'
});
Ext.create('Ext.data.Store', {
storeId: 'comboStore',
model: 'ComboModel',
data: [{
ComboId: 1,
Label: '1st Label'
}, {
ComboId: 2,
Label: '2nd Label'
}]
});
Ext.create('Ext.data.Store', {
storeId: 'gridStore',
model: 'GridModel',
data: [{
Id: 1,
Value: 1
}, {
Id: 2,
Value: 2
}, {
Id: 3,
Value: 1
}, {
Id: 4,
Value: 2
}]
});
Ext.create('Ext.grid.Panel', {
width: 400,
height: 200,
renderTo: 'ct',
plugins: [
Ext.create('Ext.grid.plugin.RowEditing', {
clicksToEdit: 2,
listeners: {
edit: function(editor, e) {
console.log(gridStore.getModifiedRecords());
}
}
})
],
store: Ext.data.StoreManager.lookup('gridStore'),
forceFit: true,
columns: [{
dataIndex: 'Id',
header: 'ID'
}, {
dataIndex: 'Value',
header: 'Label',
editor: {
xtype: 'combobox',
displayField: 'Label',
valueField: 'ComboId',
queryMode: 'local',
store: Ext.data.StoreManager.lookup('comboStore'),
allowBlank: true
},
renderer: function(value) {
var rec = comboStore.getById(value);
return rec ? rec.get('Label') : value;
}
}],
renderTo: Ext.getBody()
});

ExtJS how to create a custom field from a custom component

I have my application (ExtJS 4.2.1) and I have a form:
xtype: 'form',
bodyPadding: 10,
autoScroll: false,
itemId: 'editForm',
defaults: {
msgTarget: 'side',
xtype: 'textfield'
},
//layout:'anchor',
items: [{
xtype: 'combobox',
itemId: 'cboEmployer',
store: Ext.create('App.store.catalog.Employer', {
autoLoad: true
}),
displayField: 'Description',
valueField: 'EmployerId',
fieldLabel: 'Company',
name: 'EmployerId',
queryMode: 'local',
allowBlank: false,
},{
xtype: 'radiogroup',
fieldLabel: 'Type',
name: 'RequestInAdvance',
columns: 2,
items: [{
boxLabel: 'Normal',
name: 'RequestInAdvance',
inputValue: 0,
checked: true
}, {
boxLabel: 'Advanced',
name: 'RequestInAdvance',
inputValue: 1
}
]
}, {
xtype: 'fieldset',
title: 'Date selection',
defaults: {
labelWidth: 89,
anchor: '100%',
layout: {
type: 'hbox',
defaultMargins: {
top: 0,
right: 5,
bottom: 0,
left: 0
}
}
},
items: [{
xtype: 'highlightdate', // <- This is a custom datepicker but I need it to be a field type
name: 'SelectedDates',
itemId: 'datePicker'
}],
},
],
buttons: [{
text: 'Save',
action: 'commit',
glyph: Glyphs.SAVE,
disabled: true
}],
xtype: 'highlightdate' is a custom datepicker and I need to do custom form Validation so I can mark the element as error:
In my validation method I have:
var fieldMatch = Ext.ComponentQuery.query('field[name=' + error.field + ']');
if (fieldMatch.length) {
// add extra validaiton message to the offending field
fieldMatch[0].markInvalid(error.message);
}
So when I try to set an error to my highlightdate xtype It can be found becuase is not a field.
Is there a way to workaround this?
xtype is just a shortname for your custom 'highlightdate' class and can be replaced by the new Namespace.CustomClass({cfg}) notation. What you need to figure out is: what base class does this custom class extend? If it extends Ext.form.field.Base or Ext.form.field.Text for ex. than it's also a field and inherits all the properties from it.

ExtJS4 Reload grid Panel in button handler

I'm working with ExtJS4 and trying to build a search feature using a form. I've got the form displayed and a user enters one of 4 criteria and clicks Search, the grid is then built and shows the results from a JSON call.
What I'm trying to achieve is to allow the user to be able to enter different search criteria and click Search again and have the grid updated to show the new results. In my first attempt the grid is rendered for each click of Search and in my second attempt it simply pushes the results of the search into the grid without removing the previous entries.
Here's my current setup:
Ext.define('job',{
extend:'Ext.data.Model',
fields:['account_name', 'account_number','job_number','contract_year','program','type', 'version']
})
Ext.onReady(function(){
var formPanel = Ext.widget('form', {
renderTo: 'search',
frame: true,
width: 350,
bodyPadding: 5,
bodyBorder: false,
title: 'Search',
defaults: {
anchor: '100%'
},
{
xtype: 'combo',
name: 'jobyear',
fieldLabel: 'Job Year',
store:
new Ext.data.SimpleStore({
fields: ['year'],
data: [
['2008'],['2009'],['2010'],['2011'],['2012']
] //end of data
}),
displayField: 'year',
typeAhead: true,
emptyText: 'Select a year'
}], //end of items
dockedItems: [{
xtype: 'container',
dock: 'bottom',
layout: {
type: 'hbox',
align: 'middle'
},
padding: '10 10 5',
items: [{
xtype: 'component',
id: 'formErrorState',
baseCls: 'form-error-state',
flex: 1
}, {
xtype: 'button',
formBind: true,
id: 'search',
disabled: true,
text: 'Search',
width: 140,
height: 35,
handler: function() {
var columns = [
{xtype: 'rownumberer',sortable: true},
{text: 'School Name', sortable:true,dataIndex:'account_name'},
{text: 'Acct Number', sortable:true,dataIndex:'account_number'},
{text: 'Job Number',sortable:true,dataIndex:'job_number'},
{text: 'Version',sortable:true,dataIndex:'version'},
{text: 'Contract Year',sortable:true,dataIndex:'contract_year'},
{text: 'Program', sortable:true,dataIndex:'program'},
{text: 'Job Type', sortable:true,dataIndex:'type'}
]; // end columns
var userGrid = new Ext.grid.Panel({
id: 'FOO',
multiSelect:true,
store: store,
columns: columns,
stripeRows: true,
title: 'Results',
renderTo: Ext.get('results'),
dockedItems: [{
xtype: 'pagingtoolbar',
store: store,
dock: 'bottom',
displayInfo: true
}],
})
var form = this.up('form').getForm();
var store = new Ext.data.Store({
model: 'job',
pageSize: 10,
autoLoad: true,
remoteSort:true,
proxy: {
actionMethods: {
read: 'POST'
},
type: 'ajax',
fields: ['job_number', 'account_name', 'account_number', 'contract_year','program','type','version'],
url: '/search?'+ form.getValues(true),
reader:{
type: 'json',
root: 'results',
totalProperty: 'totalCount'},
}, //end proxy
sorters:[{
property:'version',
direction:'ASC'
}]
}).on('load', function(){
userGrid.reconfigure(this); // ???
});
} // end button handler
}] //end items
}] // end dockeditems
});
});
I've tried refreshing the grid and calling load() but I don't think I've hit yet on the right combination. I'd like the grid contents to be replaced with those from the latest ajax call to /search.
You should not create a new panel and a store on each search button click, so move it out of the button handler. If you just call load({params:{search:'whatever'}}) on the store of the grid when user pushes search button you will get the new data populated in your grid automatically. You don't need to reconfigure the grid or do anything else. Essentially the grid is bound to the store and when the store data changes the view behind the grid will automatically refresh.
I got this solved by following some of DmitryB's advice. I inherited this code and after some massaging I got it working as intended. Below is my final solution. In the handler function on the button you need to be sure and update the URL of the proxy defined in the store so that when you call store.load() it's correct.
Ext.require([
'Ext.form.*',
'Ext.grid.*',
'Ext.data.*',
'Ext.dd.*'
//'extjs.SlidingPager'
]);
/*Setup Data Model*/
Ext.define('job',{
extend:'Ext.data.Model',
fields:['account_name', 'account_number','job_number','contract_year','program','type', 'version']
})
Ext.onReady(function(){
var formPanel = new Ext.widget('form', {
renderTo: 'search',
frame: true,
width: 350,
bodyPadding: 5,
bodyBorder: false,
title: 'Search',
defaults: {
anchor: '100%'
},
fieldDefaults: {
labelAlign: 'left',
msgTarget: 'none'
},
items: [{
xtype: 'textfield',
name: 'jobnumber',
fieldLabel: 'Job Number',
allowBlank: true,
minLength: 7,
maxLength: 7
}, {
xtype: 'textfield',
name: 'accountnumber',
fieldLabel: 'Account Number',
allowBlank: true,
minLength: 6,
maxLength: 7
}, {
xtype: 'textfield',
name: 'customername',
fieldLabel: 'Customer Name',
allowBlank: true,
}, {
xtype: 'combo',
name: 'jobyear',
fieldLabel: 'Job Year',
store:
new Ext.data.SimpleStore({
fields: ['year'],
data: [
['2008'],['2009'],['2010'],['2011'],['2012']
] //end of data
}),
displayField: 'year',
typeAhead: true,
emptyText: 'Select a year'
}], //end of items
dockedItems: [{
xtype: 'container',
dock: 'bottom',
layout: {
type: 'hbox',
align: 'middle'
},
padding: '10 10 5',
items: [{
xtype: 'button',
formBind: true,
id: 'search',
disabled: true,
text: 'Search',
width: 140,
height: 35,
handler: function() {
store.proxy.url = '/search?' + formPanel.getForm().getValues(true)
store.load();
} // end button handler
}] //end items
}] // end dockeditems
});
var store = new Ext.data.Store({
model:'job',
pageSize:10,
autoLoad: false,
remoteSort:true,
proxy:{
type:'ajax',
fields:['job_number', 'account_name', 'account_number', 'contract_year','program','type','version'],
url: '',
reader:{
totalProperty:'totalCount',
type: 'json',
root: 'results'
},
actionMethods: 'POST'
},
sorters:[{
property:'version',
direction:'ASC'
}]
});
var columns = [
{xtype: 'rownumberer',sortable: true},
{text: 'School Name', sortable:true,dataIndex:'account_name'},
{text: 'Acct Number', sortable:true,dataIndex:'account_number'},
{text: 'Job Number',sortable:true,dataIndex:'job_number'},
{text: 'Version',sortable:true,dataIndex:'version'},
{text: 'Contract Year',sortable:true,dataIndex:'contract_year'},
{text: 'Program', sortable:true,dataIndex:'program'},
{text: 'Job Type', sortable:true,dataIndex:'type'}
]; // end columns
var userGrid = new Ext.grid.Panel({
id: 'userGrid',
multiSelect: false,
store: store,
columns: columns,
stripeRows: true,
title: 'Results',
renderTo: 'results',
dockedItems: [{
xtype: 'pagingtoolbar',
store: store,
dock: 'bottom',
displayInfo: true
}],
})
});

Resources