PDA

View Full Version : [UNKNOWN][3.x] TabPanel's setting of its defined activeTab during render



Animal
15 Dec 2009, 4:02 AM
Setting the active item in a CardLayout calls doLayout to ensure that the item being activated is fully rendered.

The trouble with the way TabPanel activates its configured active tab now, is that it does this during the rendering process.

Laying out must happen only in response to a doLayout call, not once during the rendering process, and then again when the doLayout call is made to actually render the Viewport or Window, or whatever it is that contains the TabPanel.

The fix is to set the active item on layout:



Ext.override(Ext.TabPanel, {
afterRender : function(){
Ext.TabPanel.superclass.afterRender.call(this);
if(this.autoTabs){
this.readTabs(false);
}
},

onLayout: function() {
Ext.TabPanel.superclass.onLayout.call(this);

// On first layout (The activeTab property still present), activate it.
if(this.activeTab !== undefined){
var item = Ext.isObject(this.activeTab) ? this.activeTab : this.items.get(this.activeTab);
delete this.activeTab;
this.setActiveTab(item);
}
}
});

Condor
15 Dec 2009, 4:36 AM
Your solution doesn't work. setActiveTab will set the activeTab property, so the next onLayout will call setActiveTab again.

You could use:

Ext.override(Ext.TabPanel, {
afterRender : function(){
Ext.TabPanel.superclass.afterRender.call(this);
if(this.autoTabs){
this.readTabs(false);
}
},
onLayout: function() {
Ext.TabPanel.superclass.onLayout.call(this);
if(Ext.isDefined(this.activeTab)){
var item = this.getComponent(this.activeTab);
if(item != this.layout.activeItem){
delete this.activeTab;
this.setActiveTab(activeTab);
}
}
});

Animal
15 Dec 2009, 5:12 AM
OK, of course. TabPanel maintains an activeTab property as well as using it as a config.

Perhaps then, TabPanel's initComponent should transfer it into this.initialActiveTab, and then the code would be



Ext.override(Ext.TabPanel, {
afterRender : function(){
Ext.TabPanel.superclass.afterRender.call(this);
if(this.autoTabs){
this.readTabs(false);
}
},

onLayout: function() {
Ext.TabPanel.superclass.onLayout.call(this);

// On first layout (The initialActiveTab property still present), activate it.
if(this.initialActiveTab !== undefined){
var item = this.getComponent(this.initialActiveTab);
if(item) { // If it's not there, leave it for when it may be added.
delete this.initialActiveTab ;
this.setActiveTab(item);
}
}
},

onAdd: function(newItem) {
Ext.TabPanel.superclass.onAdded.apply(this, arguments);

// Activate any predefined activeTab as soon as it is added
if(this.rendered && this.initialActiveTab !== undefined){
var item = this.getComponent(this.initialActiveTab);
if(item === newItem) { // If the newly aded item was the one to be initially active, activate it.
delete this.initialActiveTab ;
this.setActiveTab(item);
}
}
}
});

tobiu
15 Dec 2009, 3:04 PM
hi nige,

i think we wrote about the same issue. i came up with a different approch:
http://www.extjs.com/forum/showthread.php?t=87816

kind regards and sorry that i missed this topic,
tobiu

Animal
16 Dec 2009, 12:07 AM
It's a similar issue, but this is to do with performance, and layouts. This will cause a layout to be done twice. Once during initial render. And then the afterRender event of the Viewport (or Ext.Window, or whatever is the outermost Container) will explicitly call doLayout which will cascade down and lay out the active tab all over again.