PDA

View Full Version : TabPanel auto activate added tabs



maxserv-remco
6 Oct 2009, 5:56 AM
Hi,

I'm trying to let a TabPanel auto Activate any new tabs that are being added to them.
So I figured I'd use the 'add' event on the TabPanel, as seen in this code example:


var tabMain = new Ext.TabPanel({
region : 'center',
id: 'tab-main',
activeTab : 0,
items : [dashboardPanel],
listeners: {
add: function(container,component,index) {
container.doLayout();
container.setActiveTab(index);
//OR: container.setActiveTab(component.id);
}

}
});Now when I add a Panel to the TabPanel, the event fires, and the passed arguments do contain the objects they should (e.g: console.log(component.id) shows the correct Panel id and console.log(index) gives the correct items[] index), so everything SHOULD work.. but ofcourse it doesnt.
FireBug gives me a
Ext.fly(el) is null: Ext.fly(el).addClass('x-tab-strip-active');\n error, and the script halts.
If I remove the setActiveTab command, everything works, but naturally the newly added tab doesn't get activated.

Am I doing something wrong here, or overlooking anything, like the Panel not being 'ready' or something when the event is fired? Thanks in advance for any help!

pegaso52it
6 Oct 2009, 7:25 AM
Hi,
have you tryed to defer the active tab set?
eg:
container.setActiveTab.defer(50, container, [index]);

maxserv-remco
6 Oct 2009, 7:42 AM
That actually seems to work!

(Didn't know these (http://www.extjs.com/deploy/ext/docs/output/Function.html#defer) things existed)

However, it seems to be a bit of a hack, doesn't it?
I mean, it works now, but there's absolutely no guarantee that the Panel is 'completed', or whatever is happening that was causing the call to fail, within those 50 (or any other number) miliseconds. Especially because a few of the Panels being loaded into that TabPanel depend on a substantial number of Ajax calls, so a busy webserver could potentially result in JS errors for the end users.

So, thanks very much for the hint, now I've actually got something to show to my boss :D, but wouldn't there be a better way to solve it? Like waiting on the object to complete or whatever it's doing, or putting it on a callback or something? Panel only has a 'rendered' property, which doesn't do the job here, so I'm a bit clueless on where to attach this call to make the solution foolproof (and Ajaxproof ;))

Again though, thanks!

pegaso52it
6 Oct 2009, 8:00 AM
Hi,
no I do not know how it fails and I'm not able to give u any other suggestion.

In my opinion (I'm very novice in ExtJS) 50 is an arbitrary number; probably is not the
milliseconds needed to complete the add...

Try using 1 millisecond (sure, is not enough to complete the add) but probably u will see that your code will works again.

Let me know, please

Animal
6 Oct 2009, 8:08 AM
var tabMain = new Ext.TabPanel({
region : 'center',
id: 'tab-main',
activeTab : 0,
items : [dashboardPanel],
listeners: {
add: function(container,component,index) {
container.setActiveTab(component);
}

}
});

maxserv-remco
8 Oct 2009, 1:18 AM
@Animal:

That doesn't work either, still gives me the "Ext.fly(el) is null".

On the other hand, @pegaso52it:

You were right, the amount of milliseconds isn't important, just the fact that it's being deferred seems to magically solve all problems. I did a test where I would delay all Ajax calls the loaded tab makes on the server side (making it really slow, like 15 seconds to load the tab or so), and a 1 millisecond deferral still did the job.
So I'm guessing this is just some odd behavior in either the Add handler, or the setActiveTab function, but the defer() seems to completely overcome the issue without drawbacks.

Just for completeness, it doesn't matter which of these you use, they all work ;)


container.setActiveTab.defer(1,container,[component]);
container.setActiveTab.defer(50,container,[index]);
container.setActiveTab.defer(50,container,[component.id]);
Thanks again for the help.. now to fix some other pending issues :((

pegaso52it
8 Oct 2009, 1:42 AM
Thanks for your answer.
Would be nice now to have the point of view of some ExtJS's Gurus (Condor, Garcia, Animal and so on....)

In my opinion is there something of strange:
- Or deferring makes EXTJs to "consume" all pending events before the deferred code execution (In your code is there a doLayout, so many pending events to be consumed)
- Or is there some "hidden" bugs

Animal
8 Oct 2009, 1:52 AM
No, it works.

I've just run this in Firebug:



Ext.getBody().update('');
t = new Ext.TabPanel({
renderTo: document.body,
height: 400, width: 600,
id: 'tab-main',
items : {title: 'First tab', html: 'First tab content'},
listeners: {
add: function(container,component,index) {
container.setActiveTab(component);
}
}
});
(function(){
t.add({title: 'Second Tab', html: 'Second tab content'});
}).defer(5000);


And it does exactly what you'd expect. Activates each new tab as soon as it is added.

Animal
8 Oct 2009, 1:54 AM
You probably need



listeners: {
add: function(container,component,index) {
if (container.rendered) {
container.setActiveTab(component);
} else {
container.activeTab = index;
}
}
}

ExtJSNewUser
1 Dec 2009, 9:14 AM
Animal,

The below code works fine in the initial load. I am adding a grid to the Tab panel. when the user goes to some other menu, I have to remove the current grid from the panel and add the corresponding panel to it, at that point I am getting error while setting the Active tab. error this.layout.layout(), obejct doesnt support this property

if (Ext.getCmp('tbMainPanel').rendered) {
Ext.getCmp('tbMainPanel').setActiveTab(Ext.getCmp('tbMainPanel').add(grdAlertWB));} else {

Ext.getCmp('tbMainPanel').activeTab = 0;
}

I am removing the tabs like the below (tbPanel.removeAll() will also do this)

var len = Ext.getCmp('tbMainPanel').items.items.length;
for (var cntr = 0, ln = len; cntr < ln; cntr++) {
Ext.getCmp('tbMainPanel').remove(Ext.getCmp('tbMainPanel').items.items[cntr]);
}

any help is appreciated

Animal
1 Dec 2009, 10:33 AM
Looks like overnesting there. Add the GridPanel directly to the TabPanel as an immediate child item.