PDA

View Full Version : [UNKNOWN][3.0.3] Tabpanel -> tabchange-event



tobiu
15 Dec 2009, 10:50 AM
hi together,

this is not a bug, more like an "unwanted" behaviour.

when a tabPanel has the activeTab-config, the event tabchange gets fired, after the tabPanel was rendered, although there was no change of active tabs (just the activation of the first tab).

this causes problems if you want to differ between "real" changes (switching from one tab to another one) and render.

this part of Ext.TabPanel causes the problem:


// private
afterRender : function(){
Ext.TabPanel.superclass.afterRender.call(this);
if(this.autoTabs){
this.readTabs(false);
}
if(this.activeTab !== undefined){
var item = Ext.isObject(this.activeTab) ? this.activeTab : this.items.get(this.activeTab);
delete this.activeTab;
this.setActiveTab(item);
}
}


because setActiveTab() does not know, if it is the first call or not. adding a second param would solve the issue:

setActiveTab(item, firstLoad)


// private
afterRender : function(){
Ext.TabPanel.superclass.afterRender.call(this);
if(this.autoTabs){
this.readTabs(false);
}
if(this.activeTab !== undefined){
var item = Ext.isObject(this.activeTab) ? this.activeTab : this.items.get(this.activeTab);
delete this.activeTab;
this.setActiveTab(item, true);
}
}


kind regards,
tobiu

tobiu
15 Dec 2009, 11:01 AM
Ext.override(Ext.TabPanel, {
afterRender : function(){
Ext.TabPanel.superclass.afterRender.call(this);
if(this.autoTabs){
this.readTabs(false);
}
if(this.activeTab !== undefined){
var item = Ext.isObject(this.activeTab) ? this.activeTab : this.items.get(this.activeTab);
delete this.activeTab;
this.setActiveTab(item, true);
}
}
,setActiveTab : function(item, noChange){
item = this.getComponent(item);
if(!item || this.fireEvent('beforetabchange', this, item, this.activeTab) === false){
return;
}
if(!this.rendered){
this.activeTab = item;
return;
}
if(this.activeTab != item){
if(this.activeTab){
var oldEl = this.getTabEl(this.activeTab);
if(oldEl){
Ext.fly(oldEl).removeClass('x-tab-strip-active');
}
this.activeTab.fireEvent('deactivate', this.activeTab);
}
var el = this.getTabEl(item);
Ext.fly(el).addClass('x-tab-strip-active');
this.activeTab = item;
this.stack.add(item);

this.layout.setActiveItem(item);
if(this.scrolling){
this.scrollToTab(item, this.animScroll);
}

item.fireEvent('activate', item);
if(!noChange)this.fireEvent('tabchange', this, item);
}
}
});


should do for now. i changed firstLoad to noChange, since setActiveTab() is a public function and the param could be used for other purposes too.

kind regards,
tobiu

evant
15 Dec 2009, 3:26 PM
I don't necessarily agree.

How is that any different from say:



Ext.onReady(function(){
var tabs = new Ext.TabPanel({
width: 200,
height: 200,
renderTo: document.body,
listeners: {
tabchange: function(){
console.log('change');
}
}
});
new Ext.Button({
renderTo: document.body,
text: 'a',
handler: function(){
tabs.add({
title: 'x'
});
tabs.doLayout();
tabs.setActiveTab(0);
}
});
});


The active tab is changing from nothing, to something.

tobiu
16 Dec 2009, 12:10 AM
hi evant,

this topic might be the same issue like http://www.extjs.com/forum/showthread.php?t=87773, viewed from a different angle though.

i agree, that the first tab gets activated on rendering (didn't touch that event). look at the following example please:



var tabs = new Ext.TabPanel({
width: 200,
height: 200,
renderTo: document.body,
listeners: {
tabchange: function(){
console.log('change');
}
defaults: {
listeners: {
activate: function(){
console.log('activate');
}
}
}
});


so, without my change, those listeners trigger in the exact same way. there is no way to determine, if it is a "real" tabchange or just the initial activation.

if we leave it like this, then there should be a new event added to tabpanel: onRealTabchange.

kind regards,
tobiu

Animal
16 Dec 2009, 12:54 AM
I don't necessarily agree.


The active tab is changing from nothing, to something.

That's one way of looking at it. But the OP has a point in that you cannot now detect whether it is a user-initiated tab change, or just the default initial activation.

If the tabchange also has the previously active tab passed, you could check it for being falsy and if so, it would be the tab change from nothing to something.

tobiu
16 Dec 2009, 3:54 AM
hi nige,

passing the old tab would also solve this issue. a good idea i could live with ;)
in the help-forums another user also asked to pass the old tab with tachange:
http://www.extjs.com/forum/showthread.php?t=87766

kind regards,
tobiu

tobiu
16 Dec 2009, 4:04 AM
this should be the way, animal proposed:



/*
* 3.0.3
* http://www.extjs.com/forum/showthread.php?t=87816
* tabchange - event new param: oldTab
*/
Ext.override(Ext.TabPanel, {
setActiveTab : function(item){
item = this.getComponent(item);
if(!item || this.fireEvent('beforetabchange', this, item, this.activeTab) === false){
return;
}
if(!this.rendered){
this.activeTab = item;
return;
}
if(this.activeTab != item){
if(this.activeTab){
var oldEl = this.getTabEl(this.activeTab);
if(oldEl){
Ext.fly(oldEl).removeClass('x-tab-strip-active');
}
this.activeTab.fireEvent('deactivate', this.activeTab);
}
var el = this.getTabEl(item);
Ext.fly(el).addClass('x-tab-strip-active');
var oldTab = this.activeTab;
this.activeTab = item;
this.stack.add(item);

this.layout.setActiveItem(item);
if(this.scrolling){
this.scrollToTab(item, this.animScroll);
}

item.fireEvent('activate', item);
this.fireEvent('tabchange', this, item, oldTab);
}
}
});