Wednesday, 26 May 2010

ExtJS - loading grid record into form with loadRecord() but getting the displayField instead of valueField submitted.


A long title I know, but today was one of those days that every programmer dreads.. a day with a small problem that takes more than 5minutes to figure out. This one took me a whole day! Reasons; partly because of a lack of documentation, partly me giving ExtJS to much magic credit and mostly me over-thinking the problem.

The only thing I could find online that really covered it, but not in a way that was at all obvious to me is here: http://www.extjs.com/forum/showthread.php?88614-Combo-Box-question&highlight=loadrecord+combo

If you have a grid and you load that grid with combo displayField values (from the store) and use loadRecord() to populate the form you will notice that it seems to work on the outside. However when you hit submit the displayField and not the valueField are submitted! I would have assumed ExtJS would have some magic that compares the displayField value with the valueField and updates it accordingly. Wrong, the valueField is set to whatever you set it to and ExtJS will do nothing to change that.

What you need to do is, add the valueField values to the grid as well as the displayField values but not including them in the column model. This way the grid is not cluttered with combo valueField values. But how do you then get that valueField to the form combos? You need to set the hiddenName value in the combos to point to the valueField in the grid and the name to the relevant displayField.

I'm going to stop myself as I think a simple clean code example will speak louder than my confusing ramblings, so here you go:

var form = new Ext.form.FormPanel({
title : 'Test form',
width : 300,
items : [{
xtype : 'combo',
fieldLabel : 'Gender',
name : 'gender_',
hiddenName : 'gender',
store : new Ext.data.ArrayStore({
fields : ['valueField', 'displayField'],
data : [[1, 'Male'] , [2, 'Female']]
}),
mode : 'local',
valueField : 'valueField',
displayField : 'displayField'
}]
});

var toolbar = new Ext.Toolbar({
items : ['->']
});

toolbar.addButton({
text : 'Clear',
handler: function(b, e)
{
form.getForm().reset();
}
});

toolbar.addButton({
text : 'Save',
handler: function(b, e)
{
var values = form.getForm().getFieldValues();
for(var field in form.getForm().getValues())
{
alert(field+':'+values[field]);
}
}
});

form.add(toolbar);

var grid = new Ext.grid.GridPanel({
title : 'test grid',
width: 600,
height: 300,
columns : [
{id: 'id', header : 'id', dataIndex : 'id'},
{header : 'Gender', dataIndex : 'gender_'}
],
store : new Ext.data.ArrayStore({
fields : [ 'id', 'gender_', 'gender' ],
data : [
[ 34, 'Male', 1],
[ 35, 'Female', 2]
]
}),
sm: new Ext.grid.RowSelectionModel({
singleSelect: true,
listeners: {
rowselect: function(sm, row, rec) {
form.getForm().loadRecord(rec);
}
}
})
});

var win = new Ext.Window({
title : 'test',
items : [{
xtype : 'panel',
layout : 'column',
items : [form, grid]
}]
});

win.show();

Notice the '_' added to the name value of the combo.

I hope that by documenting/explaining my problem it will help others avoid a wasted day as I have.

You may have noticed it has been over 2years since my last post.. well, starting your own business will do that to a blogger :D

No comments: