PDA

View Full Version : [Solved] Extending TabPanel fails



Wolfgang
29 Mar 2010, 2:46 AM
Hello,

Extending Tabpanel fails when adding certain properties.

To illustrate, here a very basic example using a s sort of a preconfigered class - the real code looks different and adds methods and uses initComponent.


Ext.ux.WizzardPanel = Ext.extend(Ext.TabPanel, {
title: 'my title'
,items:[{title: 'tab1'}]
});
Ext.reg('wizzardpanel', Ext.ux.WizzardPanel);

When using it, it fails with:


this.items.containsKey is not a function

However when not using "items" like:


Ext.ux.WizzardPanel = Ext.extend(Ext.TabPanel, {
title: 'my title'
//,items:[{title: 'tab1'}]
});
Ext.reg('wizzardpanel', Ext.ux.WizzardPanel);

it works.

Other option like "layout" causes also a similar issue:


Ext.ux.WizzardPanel = Ext.extend(Ext.TabPanel, {
title: 'my title'
//,items:[{title: 'pre tab1'}]
,layout: 'fit'
});



this.layout.setContainer is not a function



Is the anything special to consider using Ext.TabPanel (and maybe other Container)?

Thanks in advance

P.S. Just for the records - as said before using initComponent does not make a difference - this fails also:


Ext.ux.WizzardPanel = Ext.extend(Ext.TabPanel, {
title: 'card Wizzard'
,layout: 'fit'
,border: true
,items:[{
title: 'tab1-internal'
}]
,initComponent: function(){
var config = {
region: 'center'
};
Ext.apply(this, config);
Ext.apply(this.initialConfig, config);
Ext.ux.WizzardPanel.superclass.initComponent.apply(this, arguments);
}
});

Animal
29 Mar 2010, 2:57 AM
Why would you extend TabPanel if you wanted a layout: 'fit' Panel?

Why would you call a layout: 'fit' Panel (it only has ONE child) a wizard?

You are extending to configure.

You are hardcoding items into the class!!!

Condor
29 Mar 2010, 3:16 AM
So:
1. You can't configure a TabPanel with layout:'fit', because it always uses layout:'card'. For a wizard you probably don't want to use a TabPanel, but a normal Panel with layout:'card'.
2. Subclassing is only useful when you intend to create descendants or multiple instances with different configurations.
3. You should not define objects in the prototype (e.g. 'items'). You should define these in initComponent (or constructor).

Assuming you actually conform to #2 you would end up with:

Ext.ux.WizardPanel = Ext.extend(Ext.Panel, {
initComponent: function(){
var config = {
region: 'center',
title: 'Card Wizard',
layout: 'card',
border: true,
items: [{
title: 'tab1-internal'
}]
};
Ext.apply(this, config);
Ext.apply(this.initialConfig, config);
Ext.ux.WizardPanel.superclass.initComponent.apply(this, arguments);
}
});
or

Ext.ux.WizardPanel = Ext.extend(Ext.Panel, {
constructor: function(config){
Ext.ux.WizardPanel.superclass.constructor.call(this, Ext.apply({
region: 'center',
title: 'Card Wizard',
layout: 'card',
border: true,
items: [{
title: 'tab1-internal'
}]
}, config));
}
});
(I prefer the second one for simplicity)

Wolfgang
29 Mar 2010, 3:44 AM
Thank you for looking into it.
As said before, i reduced the showcase to a minimum, thats why it looks like just a pre-config class.
Granted - layout 'fit' does not make sense.

So here maybe a better way to illustrate the issue - again i kept code as simple as possible.


Ext.ux.MyCard1 = Ext.extend(Ext.Panel, {
title: 'Card1'
})
Ext.reg('mycard1', Ext.ux.MyCard1);

Ext.ux.MyCard2 = Ext.extend(Ext.Panel, {
title: 'Card2'
})
Ext.reg('mycard2', Ext.ux.MyCard2);

Ext.ux.WizzardPanel = Ext.extend(Ext.TabPanel, {
border: true
,height: 300
,width: 300

,initComponent: function(){
var config = {
layout: 'card' // causes issue
,activeItem:0
,items: [{
xtype: 'mycard1'
,title: 'Step 1'
}
,{
xtype: 'mycard2'
,title: 'Step 2'
}]
};
Ext.apply(this, config);
Ext.apply(this.initialConfig, config);
Ext.ux.WizzardPanel.superclass.initComponent.apply(this, arguments);
}
});
Ext.reg('wizzardpanel', Ext.ux.WizzardPanel);


and for testing:


var y = new Ext.Window({items: [{xtype: 'wizzardpanel'}]});
y.show();

The option "layout: 'card'" causes:


this.layout.setContainer is not a function

Wolfgang
29 Mar 2010, 3:56 AM
So:
....

thanks for the fast reply.
Pls ignore my 2nd post for now, since it was posted just before having seen your answer.

Wolfgang
29 Mar 2010, 4:25 AM
First off all i got it working (will attach code - maybe someone else follows this thread).


So:
...
3. You should not define objects in the prototype (e.g. 'items'). You should define these in initComponent (or constructor).
...


In particular for the property "items" it works when putting into "initComponent".
But i do not understand why i must not put it into the "public" part (prototype) like "title" or "width".
Refering to Extending_Ext2_Class (http://www.extjs.com/learn/Tutorial:Extending_Ext2_Class) i thought that any properties that should be public accessable, need to be placed outside of "initComponent". :-?


As said here the code. Note that the panels added via items are just for demonstration. Of cause the Wizzard should take them dynamically.


Ext.ux.WizzardPanel = Ext.extend(Ext.Panel, {
border: true
,height: 300
,width: 300

,initComponent: function(){
var config = {
layout: 'card'
//,region: 'center'
,activeItem:0
,items: [{
xtype: 'mycard1'
,title: 'Step 1'
}
,{
xtype: 'mycard2'
,title: 'Step 2'
}]

,bbar:[
'->'
,{
text:'« Previous'
,disabled:true
}
,{
text:'Next »'
}
,{
text:'Cancel'
}]

};
Ext.apply(this, config);
Ext.apply(this.initialConfig, config);
Ext.ux.WizzardPanel.superclass.initComponent.apply(this, arguments);
}
});
Ext.reg('wizzardpanel', Ext.ux.WizzardPanel);