PDA

View Full Version : [FIXED-406][3.1.0] listEmptyText on ComboBox ineffective



Gjslick
4 Jan 2010, 12:20 PM
Ext version tested:


Ext 3.1.0 rev. 5847



Adapter used:


ext



css used:


only default ext-all.css





Browser versions tested against:


IE8
IE7
FF3.5 (firebug 1.4.5 installed)
Safari 4
Chrome 3



Operating System:


WinXP Pro



Description:


The listEmptyText config is ineffective for Ext.form.ComboBox. This was attempted to be fixed in 3.0.0 a while back (this thread: http://www.extjs.com/forum/showthread.php?t=76286&highlight=listEmptyText), but still seems to not be working correctly, especially with 'local' mode ComboBox's which are being used to emulate standard HTML select elements. Created a simple test case below.

When the expand button is clicked, the DataView seems like it is getting shown, but there is no empty text inside of it, and it is only a few pixels high (except on IE7, where it is the correct size, but still no empty text).



Test Case:



new Ext.form.FormPanel( {
renderTo: Ext.getBody(),
border: false,
layout: 'form',

items: {
xtype: 'combo',
fieldLabel: "Test Combo",

store: new Ext.data.ArrayStore( {
fields: [ 'display', 'value' ],
data: []
} ),
displayField: 'display',
valueField: 'value',

emptyText: "Select...",
listEmptyText: "No Items",

mode: 'local',
triggerAction: 'all',
editable: false,
forceSelection: true
}
} );
Debugging already done:


none



Possible fix:


not provided

art.home.ext
4 Jan 2010, 2:52 PM
First question to Ext team :
in ext-all-debug-3.1.0.js line 25097, is it necessary to defer el.update with hasSkippedEmptyText variable ?

refresh : function(){
...
if(records.length < 1){
if(!this.deferEmptyText || this.hasSkippedEmptyText){
el.update(this.emptyText);
}
...
}
this.hasSkippedEmptyText = true;
}
Second question to Ext team again :
Do you think we may see a viewConfig property on ComboBox in next releases ?
Maybe the use of deferEmptyText: false would have helped here.
I tried in many combo listeners without success.


And the last for you :

The listEmptyText config is back to being ineffective on Ext.form.ComboBox. This was fixed in 3.0.0 a while back (this thread: http://www.extjs.com/forum/showthread.php?t=76286&highlight=listEmptyText), but seems to have broken again in 3.1.0.



Was the listEmptyText config really effective in 3.0.0 ? or patched with the link you gave ?


I've workarounded this problem with this "not the best" patch :


// Patch listEmptyText problem in 3.1.0 (showthread.php?p=424116)
var yourCombo = new Ext.form.ComboBox({...});

// appropriate {single:true}
yourCombo.addListener('expand',function(){if (this.view && this.store && this.store.data /* necessary ? */ && (this.store.getCount() == 0)) this.view.refresh();},yourCombo ,{single:true});



Hope this helps

Gjslick
4 Jan 2010, 3:28 PM
Was the listEmptyText config really effective in 3.0.0 ? or patched with the link you gave ?


That's a very good question actually. Upon trying the test case with Ext 3.0.0 and the original fix implemented as an override, listEmptyText is still ineffective. Checking my original attached example in that thread, it had to do with no matches being found when querying the combobox in remote mode only.

So I guess that it's not entirely true that listEmptyText was ever working correctly. I'll update my original post to reflect that. Thanks for looking into this.

hendricd
4 Jan 2010, 7:09 PM
@Gjslick -- After studying this a bit, it's clear that Combo's were not originally designed for the 'behavior' you had in mind back then. :-?

Give these a shot (remote and local), (against 5847) and let us know how things look:



Ext.override( Ext.form.ComboBox , {
initList : function(){
if(!this.list){
var cls = 'x-combo-list';

this.list = new Ext.Layer({
parentEl: this.getListParent(),
shadow: this.shadow,
cls: [cls, this.listClass].join(' '),
constrain:false,
zindex: 12000
});

var lw = this.listWidth || Math.max(this.wrap.getWidth(), this.minListWidth);
this.list.setSize(lw, 0);
this.list.swallowEvent('mousewheel');
this.assetHeight = 0;
if(this.syncFont !== false){
this.list.setStyle('font-size', this.el.getStyle('font-size'));
}
if(this.title){
this.header = this.list.createChild({cls:cls+'-hd', html: this.title});
this.assetHeight += this.header.getHeight();
}

this.innerList = this.list.createChild({cls:cls+'-inner'});
this.mon(this.innerList, 'mouseover', this.onViewOver, this);
this.mon(this.innerList, 'mousemove', this.onViewMove, this);
this.innerList.setWidth(lw - this.list.getFrameWidth('lr'));

if(this.pageSize){
this.footer = this.list.createChild({cls:cls+'-ft'});
this.pageTb = new Ext.PagingToolbar({
store: this.store,
pageSize: this.pageSize,
renderTo:this.footer
});
this.assetHeight += this.footer.getHeight();
}

if(!this.tpl){

this.tpl = '<tpl for="."><div class="'+cls+'-item">{' + this.displayField + '}</div></tpl>';

}

/**
* The {@link Ext.DataView DataView} used to display the ComboBox's options.
* @type Ext.DataView
*/
this.view = new Ext.DataView({
applyTo: this.innerList,
tpl: this.tpl,
singleSelect: true,
selectedClass: this.selectedClass,
itemSelector: this.itemSelector || '.' + cls + '-item',
emptyText: this.listEmptyText
});

this.mon(this.view, {
containerclick : this.onViewClick,
click : this.onViewClick,
scope :this
});

this.bindStore(this.store, true);

if(this.resizable){
this.resizer = new Ext.Resizable(this.list, {
pinned:true, handles:'se'
});
this.mon(this.resizer, 'resize', function(r, w, h){
this.maxHeight = h-this.handleHeight-this.list.getFrameWidth('tb')-this.assetHeight;
this.listWidth = w;
this.innerList.setWidth(w - this.list.getFrameWidth('lr'));
this.restrictHeight();
}, this);

this[this.pageSize?'footer':'innerList'].setStyle('margin-bottom', this.handleHeight+'px');
}
}
},
onViewClick : function(doFocus){
var index = this.view.getSelectedIndexes()[0],
s = this.store,
r = s.getAt(index);
if(r){
this.onSelect(r, index);
}else {
this.onEmptyResults();
}
if(doFocus !== false){
this.el.focus();
}
},
onEmptyResults : function(){
this.collapse.defer(
this.listEmptyText ? 600 :0,
this
);
}

});

Gjslick
4 Jan 2010, 10:34 PM
Doug, I completely agree. When I was originally looking into this a few months ago, it seemed like the addition of the listEmptyText config for 3.0.0 was an afterthought at best. If I remember correctly, the original implementation only worked in one very specific situation, and only having to do with remote mode. Then after the thread that I mentioned, listEmptyText worked for remote mode, but not local mode.

Your override seems to be working great so far though. I did a bit of testing with local and remote modes, and they both seem to be working nicely. I then plugged it into my application, and all of the listEmptyText's for combos in local mode came to life, while the others still worked as normal.

It did need one small addition for local mode though, for when there is no initial store data, and the trigger button is clicked (as opposed to the combo having some text typed into it):


/**
* The {@link Ext.DataView DataView} used to display the ComboBox's options.
* @type Ext.DataView
*/
this.view = new Ext.DataView({
applyTo: this.innerList,
tpl: this.tpl,
singleSelect: true,
selectedClass: this.selectedClass,
itemSelector: this.itemSelector || '.' + cls + '-item',
emptyText: this.listEmptyText,
deferEmptyText: false
});
There is one issue that I've come across however, and that is when the combo box is tabbed away from while the listEmptyText is open. If forceSelection is true, tabbing away from the combo will not reset the combo's value back to its previous state. However, clicking anywhere in the document after the combo is tabbed away, causes the value to be reset correctly. This does not happen without the override.

Nice job on this fix though. Seems to be working well, save for that one issue.

-Greg

hendricd
6 Jan 2010, 1:46 PM
Fixed in SVN 5850 (for Ext 3.1.0+)

Also fixed the dropdown dismissal on blur(tab). ;)

Gjslick
6 Jan 2010, 4:21 PM
Thanks Doug, it's working nicely B)

-Greg