PDA

View Full Version : [FIXED][2.x,3.x] Empty items array



Condor
9 Jul 2009, 4:46 AM
Ext doesn't handle an empty Container items array correctly.

Example: 2 column radiogroup without items (to be filled later by an Ajax request)

new Ext.form.RadioGroup({
items: [{
columnWidth: .5,
items: []
},{
columnWidth: .5,
items: []
}]
});

Instead of ignoring it it tries to add the empty array as a single component (which add ignores in Ext 3 and fails in Ext 2).

Suggested fix:

Ext.override(Ext.Container, {
initComponent : function(){
Ext.Container.superclass.initComponent.call(this);
this.addEvents(
'afterlayout',
'beforeadd',
'beforeremove',
'add',
'remove'
);
this.enableBubble('add', 'remove');
var items = this.items;
if(items){
delete this.items;
if(Ext.isArray(items)){
if(items.length > 0){
this.add.apply(this, items);
}
}else{
this.add(items);
}
}
}
});

evant
9 Jul 2009, 4:55 AM
This is pretty much how the code is in SVN, it checks if it's an array and has a length > 0.

Condor
9 Jul 2009, 5:18 AM
The code in SVN is:

if(Ext.isArray(items) && items.length > 0){
this.add.apply(this, items);
}else{
this.add(items); // shouldn't be called for empty arrays
}

Condor
9 Jul 2009, 5:22 AM
Now I think about it...

The fix for Ext 2.x should be:

Ext.override(Ext.Container, {
initComponent : function(){
Ext.Container.superclass.initComponent.call(this);
this.addEvents(
'afterlayout',
'beforeadd',
'beforeremove',
'add',
'remove'
);
var items = this.items;
if(items){
delete this.items;
if(Ext.isArray(items)){
if(items.length > 0){
this.add.apply(this, items);
}
}else{
this.add(items);
}
}
}
});

But for Ext 3.x it can simply be:

Ext.override(Ext.Container, {
initComponent : function(){
Ext.Container.superclass.initComponent.call(this);
this.addEvents(
'afterlayout',
'beforeadd',
'beforeremove',
'add',
'remove'
);
this.enableBubble('add', 'remove');
var items = this.items;
if(items){
delete this.items;
/*if(Ext.isArray(items) && items.length > 0){
this.add.apply(this, items);
}
}else{*/
this.add(items);
/*}*/
}
}
});
(add already handles an array parameter)

evant
9 Jul 2009, 6:07 AM
Right I'm with you now. Fixed in SVN.

aleczapka
4 Sep 2009, 12:54 AM
Hi,

I see you fixed it for initComponent, but Ext.apply still messes up the items.

If you need more info I can provide some debug.

mystix
4 Sep 2009, 1:25 AM
If you need more info I can provide some debug.

that would be super. i for one have gained absolutely nothing from reading that one line description. :-?

aleczapka
4 Sep 2009, 3:36 AM
Hey,

Sorry for the delay but currently at work ;)
Please note, there is a possibility it's me doing something wrong here (extjs noob) so don't get mad plz :">


Here is the code, just put it under extjs/examples and it should work.
All works, if you uncomment this line:


//fixItems(theForm);



I also noticed that after using Ext.apply the items inside my component were not like they supposed to be, eg. missing each() and various other functions.



<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>Apply Bug?</title>
<link rel="stylesheet" type="text/css" href="../../resources/css/ext-all.css" />
<script type="text/javascript" src="../../adapter/ext/ext-base.js"></script>
<script type="text/javascript" src="../../ext-all.js"></script>
<script type="text/javascript">
Ext.onReady(function(){
function fixItems(obj) {
var items = obj.items;
if(items){
delete obj.items;
if(Ext.isArray(items)){
if(items.length > 0){
obj.add.apply(obj, items);
}
}else{
obj.add(items);
}
}
}

var theForm = new Ext.FormPanel({
frame: false
});

//do some stuff with theForm

Ext.apply(theForm, {
frame: true,
items: [
{fieldLabel: 'Label1', name: 'data1', xtype: 'textfield'},
{fieldLabel: 'Label2', name: 'data2', xtype: 'textfield'}
]
});

//fixItems(theForm); //uncommment this to make it work

var config = {items: theForm};
var win = new Ext.Window(
Ext.applyIf(config, {
minimizable: true,
maximizable: true
})
);

win.render(document.body);
win.show();


})
</script>

</head>
<body>
</body>
</html>

Condor
4 Sep 2009, 3:53 AM
You can't do this on a created component:

Ext.apply(theForm, {
frame: true,
items: [
{fieldLabel: 'Label1', name: 'data1', xtype: 'textfield'},
{fieldLabel: 'Label2', name: 'data2', xtype: 'textfield'}
]
});
(frame and items are not writable properties of FormPanel!)

You should either set these in a config object before you create the panel or use the public methods (e.g. add() to add items).

aleczapka
4 Sep 2009, 3:58 AM
Oh I see.. my bad, sorry for the false alarm then


One note though: setting frame:true in Ext.apply does work... so I am kinda confused about not writable properties of FormPanel... and it doesn't state anywhere that it's not writable, unless again, I miss something.

I am not questioning your knowledge Condor, I only want to understand.

Thx in advance for any pointers in right direction.