ExtJS grid combo renderer not working - extjs

I have a grid in my ExtJS 4.2.1 application that has an editable column with combo editor.
I need to render the column with the value from the DisplayField of the combo but the comboStore.getCount() = 0
Here is my grid:
Ext.define('App.employee.Grid', {
extend: 'Ext.grid.Panel',
requires: ['Ext.grid.plugin.CellEditing'],
alias: 'widget.employee.grid',
config: {
LocationId: 0
},
initComponent: function() {
var me = this,
store = me.buildStore(),
comboStore = Ext.create('App.store.catalog.Location', { autoLoad: true });
me.rowEditing = Ext.create('Ext.grid.plugin.RowEditing', {
clicksToMoveEditor: 1,
autoCancel: false,
listeners: {
edit: function(editor, e) {
}
}
});
me.cellEditing = new Ext.grid.plugin.CellEditing({
clicksToEdit: 1
});
Ext.applyIf(me, {
plugins: [me.rowEditing],
columns: [{
xtype: 'rownumberer',
text: '#',
width: 50,
sortable: false,
align: 'center'
//locked: true
},{
text: 'Number',
dataIndex: 'EmployeeNumber',
align: 'center',
width: 90
}, {
text: 'Name',
dataIndex: 'EmployeeName',
flex: 1
}, {
text: 'Location',
dataIndex: 'LocationId',
width: 140,
renderer: function(value) {
// HERE!!!
// me.comboStore.getCount() = 0 so I never get a record
var record = me.comboStore.findRecord('LocationId', value);
return record.get('Description');
},
editor: {
xtype: 'combobox',
typeAhead: true,
triggerAction: 'all',
store: comboStore,
displayField: 'Description',
valueField: 'LocationId',
queryMode: 'local',
listConfig: {
width: 250,
// Custom rendering template for each item
getInnerTpl: function() {
return '<b>{Code}</b><br/>(<span style="font-size:0.8em;">{Description}</span>)';
}
}
}
}],
store: store,
});
me.callParent(arguments);
}
});
The problem is in the renderer function because the comboStore is always empty. The strange thing is that in my view If I click to edit the row and open the combo the combo has values.
[UPDATE]
What I think is that my comboStore has a delay when loading so the renderer is fired before the comboStore gets loaded. I figure this out because if I debug in chrome and I wait a few seconds, then it works... but don't know how to force to wait until comboStore is loaded.
Any clue on how to solve this? Appreciate any help.

A couple of solutions:
Ensure that the combo store is loaded before the grid store. This can be done by loading the combo first and from load event of its store trigger the grid store load. The disadvantage is that it adds unnecessary delay so this method impairs the user experience.
Load all needed stores in one request. It requires a bit of coding but it saves server roundtrip so it's a very valuable approach. Store loadData method is used to actually load store with the received data. You would, of course, first call it on combo, then on the grid.
The best method that I use almost exclusively is to turn the whole thing upside down and link display field to the store, not value field. Server must return both display and value fields in the grid store and a little piece of code that updates both fields in the grid store after editing is complete is required. This method is demonstrated here: Remote Combo in ExtJS Grid

Related

Error in getting value of first row from the table in ExtJS

I'm new to ExtJS. So finding little difficult in understanding many things.
I've a sample combo box where I'm retrieving datas from the table
This is the combo box:
xtype: 'fieldset',
title: 'Dress Type',
items: [{
xtype: 'combobox',
name: 'dresses',
forceNewStore: true,
queryMode: 'local',
displayField: "description",
valueField: "description",
mapperId: 'getavailabletype',
emptyText: 'Select Type
forceSelection: true,
maskRe: /[A-Za-z0-9]/,
margin: '15px',
allowBlank: false,
triggers: {
clear: {
cls: 'x-form-clear-trigger',
handler: function() {
this.reset();
}
}
},
}]
Here is the way I'm trying to retain the first value of the table:
me.down("combobox[name=dresses]").setValue(me.down("combobox[name=dresses]").store.getAt('0').get('description'));
I'm getting:
Uncaught TypeError: Cannot read property 'get' of null #getAt('0')
Please help
I don't know from what listener and component you are trying to achieve this, but from my perspective, the best place to achieve this is in the "render" event listener of the combobox.
Like so:
listeners: {
'render': function(combo) {
combo.setValue(combo.getStore().first());
}
}
Here you have a working fiddle: https://fiddle.sencha.com/#view/editor&fiddle/1qqk
OR
If you have a reference to the combo store, let's say it's in the comboStore variable, you can set the first value like this:
{
xtype: 'combobox',
value: comboStore.first()
}
Another fiddle: https://fiddle.sencha.com/#view/editor&fiddle/1qql
Now, if you are not sure that the store will be loaded by the time you initialize your combo, you can set the following listener for the combobox:
listeners: {
render: function(combo) {
var store = combo.getStore(),
setFirstStoreValFn = function() {
combo.setValue(store.first());
};
if (store.getCount()) {
setFirstStoreValFn();
}
else {
store.on('load', setFirstStoreValFn, null, {single: true})
}
}
}
So basically, it creates a reusable function that sets the combo value to the first record in the store, and then it checks if the store has records (which means that is has been loaded) it will call the function, if not - it will set a single load listener on the store which will then call the set value function.
Again, the fiddle: https://fiddle.sencha.com/#view/editor&fiddle/1qqm
you need to navigate to cmp --> store --> first record ---> data
for that me.down("combobox[name=dresses]").store.getAt(0).get('d‌​escription'))

Grid Widget column - on widget change, how to update grid store

I have a requirement to display combobox and datefield in Grid columns. So used widgetcolumn and created grid with those fields.
But now on changing data in combobox or datefield, new values should be updated in grid store so that after going to next page and coming back, values should persist in previous pages.
Can someone let me know how I can achieve this?
Fiddle: https://fiddle.sencha.com/#fiddle/183r
Option1: Use both widget and cell editor.
Add CellEditing plugin and set editor to same component as widget.
{ xtype: 'widgetcolumn', text: 'Gender', dataIndex: 'gender', flex: 1,
widget: { xtype: 'combo', store: genderStore, displayField: 'name', valueField: 'value'},
editor: { xtype: 'combo', store: genderStore, displayField: 'name', valueField: 'value'}
},
Example: https://fiddle.sencha.com/#fiddle/1843
Option2: Manually update the record.
I feel this solution is better.
widget: {xtype: 'datefield',
listeners:{
select: function(datefield, value, eOpts){
var rowIndex = datefield.up('gridview').indexOf(datefield.el.up('table'));
var record = datefield.up('gridview').getStore().getAt(rowIndex);
record.set('dob', value);
}
}
}
Example: https://fiddle.sencha.com/#fiddle/1842
To get rowIndex in widgetColumn, I referenced "How to get rowIndex in extjs widget column" DrakeES's answer.
The best solution i could find.
The function "getWidgetRecord" is not findable with the search.
It is discribed within the widget config description.
Have a look at the following Links.
https://docs.sencha.com/extjs/5.1.3/api/Ext.grid.column.Widget.html#cfg-widget
https://docs.sencha.com/extjs/6.0.2/classic/Ext.grid.column.Widget.html#cfg-widget
A config object containing an xtype.
This is used to create the widgets or components which are rendered into the cells of this column.
This column's dataIndex is used to update the widget/component's defaultBindProperty.
The widget will be decorated with 2 methods: getWidgetRecord - Returns
the Ext.data.Model the widget is associated with. getWidgetColumn -
Returns the Ext.grid.column.Widget the widget was associated with.
widget:{
xtype:'combo',
editable: false,
store: Ext.create('Ext.data.Store',{
fields:['name','text'],
data:[
{"name":"integer", "text":"Integer"},
{"name":"float","text":"Float"}
]
}),
listeners:{
select: function(combo, value, eOpts){
var record = combo.getWidgetRecord();
record.set('type', value.get('name'));
}
},
valueField:'name',
displayField:'text',
allowBlank: false
}
or
widget: {
xtype: 'textfield',
allowBlank: false,
listeners:{
change: function(textfield, value, eOpts){
var record = textfield.getWidgetRecord();
record.set('field', value);
}
}
}

ExtJs rowediting grid combo filter not work after save/update record

I have rowediting grid that gird have two combos and two text field.
when type some character on combo box that combo box filter that type word from drop down list
select that filter value and form combo and do save record ok and gird view record correctly
NEXT---
after that select one of the gird record and start edit that record.type some character on combo box but that combo don't filter that type word form drop down list.
note: that happen clearFilter(true); after save/update record. If i remove clearFilter(true); gird view combo filtered result only that why I clear filter data before load store
This is my combo box grid column
{
xtype: 'gridcolumn',
itemId: 'colId',
width: 140,
dataIndex: 'ID',
menuDisabled: true,
text: 'Name',
editor: {
xtype: 'combobox',
id: 'cbold',
itemId: 'cbold',
name: 'CBO_ID',
allowBlank: false,
displayField: 'NAME',
queryMode: 'local',
store: 'Store',
valueField: 'FIELD_ID'
}
},
This gird RowRditing
plugins: [
Ext.create('Ext.grid.plugin.RowEditing', {
saveBtnText: 'Save',
pluginId: 'grdEditor',
autoCancel: false,
clicksToMoveEditor: 1,
listeners: {
edit: {
fn: me.onRowEditingEdit,
scope: me
}
}
})
],
onRowEditingEdit function
Ext.Ajax.request({
url: 'url',
method: 'POST',
scope:this,
success : function(options, eOpts) {
var store = Ext.getStore('GridStore');
var grid = Ext.getCmp('gridFileLyt');
cbo1Store = Ext.getStore('cbo1Store');
cbo1Store.clearFilter(true);
cbo1Store.load();
cbo2Store = Ext.getStore(cbo2Store);
cbo2Store..clearFilter(true);
fldStore.proxy.extraParams = {
'_ID': ''
};
cbo2Store.load();
if(response.success){
Ext.Msg.alert('Success', response.msg);
} else {
Ext.Msg.alert('Failed', response.msg);
}
}
});
I feel i did some basic mistake please help to me
Same story here, bro.
I actively use ExtJS 4 and RowEditing since 2011, it always worked, until today when I found this bug.
I could not even Google it until I debugged and found out a workaround with clearFilter():
rowEditingPlugin.on('beforeedit', function(editor, e) {
editor.editor.form.getFields().each(function(field){
if (field instanceof Ext.form.field.ComboBox) {
field.store.clearFilter(true);
}
});
});

ExtJs: Ext.grid.Panel: Grid refreshes automatically and becomes blank

I am using a Grid to display data on a modal window.
It has two columns, 1. Label 2. TextField
The problem I am facing is whenever I enter anything in the textfield and lose focus from that textfield (by pressing TAB or clicking somewhere else), the grid clears itself completely and I get a blank grid!
I know this has something to do with the autoSync property of the Store associated with the grid.
So I set it to false autoSync: false.
After doing this the data gets retained and works fine.
BUT when I close this modal window and re-open it with the same store data, I get a blank screen!
Following is my code:
Model
Ext.define('Ext.ux.window.visualsqlquerybuilder.SQLAttributeValueModel', {
extend: 'Ext.data.Model',
fields: [
{
name: 'attribute',
type: 'string'
},
{ name: 'attributeValue',
type: 'string'
}
]
});
Store
var attrValueStore = Ext.create('Ext.data.ArrayStore', {
autoSync: true, //tried setting it to false but got error as mentioned above
model: 'Ext.ux.window.visualsqlquerybuilder.SQLAttributeValueModel'
});
GRID
Ext.define('Ext.ux.window.visualsqlquerybuilder.SQLAttributeValueGrid', {
autoRender: true,
extend: 'Ext.grid.Panel',
alias: ['widget.attributevaluegrid'],
id: 'SQLAttributeValueGrid',
store: attrValueStore,
columnLines: true,
plugins: [Ext.create('Ext.grid.plugin.CellEditing', {
clicksToEdit: 1
})],
columns: [
{ /*Expression */
xtype: 'gridcolumn',
text: 'Attribute',
sortable: false,
menuDisabled: true,
flex: 0.225,
dataIndex: 'attribute'
},
{ /*Attribute Values*/
xtype: 'gridcolumn',
editor: 'textfield',
text: 'Values',
flex: 0.225,
dataIndex: 'attributeValue'
}
],
initComponent: function () {
this.callParent(arguments);
}
});
MODAL WINDOW
var attributeValueForm = Ext.create('Ext.window.Window', {
title:'Missing Attribute Values',
id: 'attributeValueForm',
height:500,
width:400,
modal:true,
renderTo: Ext.getBody(),
closeAction: 'hide',
items:[
{
xtype: 'attributevaluegrid',
border: false,
//height: 80,
region: 'center',
split: true
}
],
buttons: [
{
id: 'OKBtn',
itemId: 'OKBtn',
text: 'OK',
handler: function () {
Ext.getCmp('attributeValueForm').close();
}
},
{
text: 'Cancel',
handler: function () {
Ext.getCmp('attributeValueForm').close();
}
}
]
});
Please help. This is making me go mad!!
It would be helpful if you could provide details on how you create the Window itself, as it may be part of the problem.
One cause of this can be that you are hiding the window instead of closing it and then creating a new instance when you re-open. This will cause your DOM to have two windows instances and may not sync the data correctly in the second instance.
Some more details on how you create the actual window would help shed some light on whether this is the case.
I would probably want to jail myself after writing this.
The real issue was that I had created a similar grid for a different modal window and since I had copied the code I missed out on changing the ID of the new grid.
Both grids had the same IDs.
Changed it now and it is working fine now.
Thanks for your help!

How to send AJAX Request only if store size is 0

How to send AJAX request for combo box by having condition that current store size is 0.
Basically I have two remote combo box which are cascaded and both are lazily loaded ( This behaviour cannot be changed)
I found even if the second combo box is cascaded based on events in first combobox upoun expansion it makes AJAX call to server ( Only first expansion though)
querymode local and autoload option will not work as it load the combo box on page load when store is created.
Given below is code snippet.
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);
}
}
To just extend your code you can do it Like so
listeners: {
beforeload: function(store, options) {
if (store.getCount() > 0) {
return false; // will abort the load operation.
}
var value = Ext.getCmp('fistcombo').value;
Ext.apply(options.params, {
valuefirst:value
});
}
}
This should work all the same in ExtJS 3.x and ExtJS4.x cause you didn't specified this. But I guess you are using 3.x
If this hangs the combo give me feedback cause there is still another but a bit more complex way.

Resources