PDA

View Full Version : [FIXED-525] Combo submits wrong value, if displayField has same entries



tobiu
3 Feb 2010, 12:13 PM
hi together,

i tested this with ext3.0.3 and 3.1.0. in my example i have 4 users, 3 named john. onSelect i show the selected id in the console (correct!). when pushing the form.submit()-button, the form submitts always the id of the first "john" (2), even if 3 or 4 was selected before. therefore click at the sent params (post) and look at the value of the user.

example-code:



Ext.onReady(function() {

var store = new Ext.data.ArrayStore({
fields: ['id', 'name']
,data : [
['1' ,'Jack']
,['2' ,'John']
,['3' ,'John']
,['4' ,'John']
]
});

Ext.ns('app');

app.win = new Ext.Window({
width : 400
,height : 200
,items :
app.form = new Ext.form.FormPanel({
labelWidth : 175
,url : 'ajaxHandler/ajaxHandler.php'
,items : [
new Ext.form.ComboBox({
store: store
,displayField:'name'
,valueField : 'id'
,typeAhead: true
,mode: 'local'
,forceSelection: true
,triggerAction: 'all'
,hiddenName : 'user'
,listeners : {
select : function(combo, record, selectedIndex){
console.log('id: ' + record.data.id);
}
}
})
]
})

,buttons : [{
text : 'submit'
,handler : function(){
app.form.getForm().submit();
}
}]
});

app.win.show();
});


kind regards,
tobiu

tobiu
4 Feb 2010, 1:10 PM
since there is no reply yet, i tracked down the bug further:

Ext.form.ComboBox


beforeBlur : function(){
var val = this.getRawValue(),
rec = this.findRecord(this.displayField, val);
if(!rec && this.forceSelection){
if(val.length > 0 && val != this.emptyText){
this.el.dom.value = Ext.isDefined(this.lastSelectionText) ? this.lastSelectionText : '';
this.applyEmptyText();
}else{
this.clearValue();
}
}else{
if(rec){
val = rec.get(this.valueField || this.displayField);
}
this.setValue(val);
}
}


is the evil part. it simply ignores the valueField by taking the rawValue and searching the store for the first match.

kind regards,
tobiu

tobiu
4 Feb 2010, 1:32 PM
this bug also is in ext-3.1

i suggest this hotfix:



Ext.override(Ext.form.ComboBox, {
beforeBlur : function(){
var val = this.getRawValue(),
rec = this.findRecord(this.displayField, val);
if(!rec && this.forceSelection){
if(val.length > 0 && val != this.emptyText){
this.el.dom.value = Ext.isDefined(this.lastSelectionText) ? this.lastSelectionText : '';
this.applyEmptyText();
}else{
this.clearValue();
}
}else{
if(rec){
if(val == rec.get(this.displayField))return;
val = rec.get(this.valueField || this.displayField);
}
this.setValue(val);
}
}
});


if the rawValue is the same string as the display-field, nothing has changed and there is no need to set the value of the input again. so there is no chance for setting a wrong value.

kind regards,
tobiu

r_honey
5 Feb 2010, 6:18 AM
I am also having the same issue:(( Switched to using selectedIndex and then querying the store for the record.

tobiu
5 Feb 2010, 8:41 AM
@r_honey:

you should try out my hotfix. it's working like a charm for me.

kind regards,
tobiu

Jamie Avins
10 Feb 2010, 5:29 PM
Fixed in svn 6037.

martin.povolny
15 Jul 2010, 4:49 AM
I don't have svn access, but the code in ExtJS 3.2.1 is still wrong! The fix applied is broken. Don't you test at all?



// private
assertValue : function(){
var val = this.getRawValue(),
rec = this.findRecord(this.displayField, val);

if(!rec && this.forceSelection){
if(val.length > 0 && val != this.emptyText){
this.el.dom.value = Ext.value(this.lastSelectionText, '');
this.applyEmptyText();
}else{
this.clearValue();
}
}else{
if(rec){
// onSelect may have already set the value and by doing so
// set the display field properly. Let's not wipe out the
// valueField here by just sending the displayField.
if (val == rec.get(this.displayField) && this.value == rec.get(this.valueField)){
return;
}
val = rec.get(this.valueField || this.displayField);
}
this.setValue(val);
}
},


the condition:


if (val == rec.get(this.displayField) && this.value == rec.get(this.valueField)){

should read


if (val == rec.get(this.displayField)){

because earlier in the code you have



var val = this.getRawValue(),
rec = this.findRecord(this.displayField, val);

so the this.value == rec.get(this.valueField) part will fail, because in rec is the first rec with the matching displayField !!

Please do test. I have adopted a large project written in ExtJS and I keep hitting with my head into the wall all the time fixing bugs...

teqneers
30 Aug 2010, 11:22 PM
I second that - the bug still exists in 3.2.1 and as far as I've seen in 3.2.2 as well.

Actually I don't know why assertValue() is called on non-editable, forced-selection comboboxes at all. I doesn't make sense to check the value that only could have been set by clicking one of the options provided. In those cases (non-editable, forced-selection) we simply override beforeBlur with an Ext.emptyFn to ensure that assertValue() isn't called.

The [FIXED]-tag should be removed from this thread...

Best regards

Stefan

Condor
30 Aug 2010, 11:45 PM
There already is a new report #1033 (http://www.sencha.com/forum/showthread.php?101123-OPEN-1033-ComboBox-reports-incorrect-value-when-non-unique-display-fields-are-used&p=475694#post475694) for this issue (with suggested fix).

teqneers
30 Aug 2010, 11:50 PM
Thanks Condor... I should have invested some more time in searching.

It's quite hard to keep track of the issues and bugs in this forum-like issue tracker ;-)

Best regards

Stefan

tobiu
31 Aug 2010, 12:32 AM
i am still using my override :)