PDA

View Full Version : Programmatically selecting a TabItem - post rendering



timefortea
10 Oct 2008, 6:24 AM
Hi all,
I've just started trying to port our HTML app to GXT and have encountered my first problem. Basically, a tab bar will be drawn according to a user's credentials, so a login window must be drawn first. Then once the user has authenticated, the retrieved credentials are used to determine what tabs are to be created. The problem is that when the tabs are created, I want to programmatically select which is the active tab - for which I am using:


tabPanel.setSelection(thisTab);This does work but I am setting a listener on each TabItem and it appears that despite setting which TabItem is to be selected, the listener on the first TabItem is always called first, before the chosen TabItem is selected (assume the first TabItem is not the one being selected).

I tried out a few tests and this does not happen pre-rendering. I am creating the TabPanel and it is being rendered behind the login window - then once the user authenticates, the details are being used to create the tabs. So am I doing something wrong? My understanding of the event model is limited and I've been unable to find much documentation on it so far.

Here is my code that is (re)creating the tabs:



public void buildTabBar()
{

<snip>

tabPanel.disableEvents(true);
tabPanel.hide();
tabPanel.removeAll();
for (String appName: appNames)
{
TabItem tabItem = new TabItem(appName);
if (!thisAppName.equals(appName))
{
tabItem.addListener(Events.Select, new SelectionListener<ComponentEvent>()
{
public void componentSelected(ComponentEvent be)
{
TabPanelEvent tbe = (TabPanelEvent)be;
TabItem tbi = (TabItem)tbe.item;
String appName = tbi.getText();

String url = sd.getUserCredentials().getURL(appName);
Window.Location.assign(url);
}
});
}
else
{
thisTab = tabItem;
}

tabPanel.add(tabItem);
tabPanel.setSelection(thisTab);
}

tabPanel.show();
tabPanel.enableEvents(true);
}
Any help appreciated.

gslender
10 Oct 2008, 4:52 PM
can't really say I understand the problem... having read your post several times I'm not sure what is not working. I notice you call the setSelection more times than you need to in the for loop - perhaps it should be outside the loop? not that this would change things that much I think.

overall, I'm unsure what your goal is and that makes it hard to know what is going wrong

cheers,
grant

timefortea
11 Oct 2008, 4:02 AM
Hi,
Thanks for taking the time to read the post, I'm sorry if it wasn't explained very well, let me try that again:
- In my onModuleLoad I am creating, amonst others things, a TabPanel (with no tabs yet) and a login Window. This gets added to the root and rendered.
- A user then enters their username/password details in the login Window and some credentials are retrieved. This includes a set of tab names and URLs. Assume there are three tabs:
App1, App2, App3
- Then, a method is called (the code I attached) which creates the tabs from the user credentials. Each tab has a listener attached so that when it is clicked on, the browser re-directs to another application on another server. Only the current tab (let's say "App2", which is not the first tab, does not have a listener.

What is happening is that the listener on the first tab (App1) is always called first, then the listener on the selected tab (App2) is called - I mean this is happening after the tab panel is built using the code I pasted in, the user hasn't clicked on anything yet. I don't want the listener on the first tab to be called unless the user physically clicks on it.

If I build the same tab bar inside my onModuleLoad and use the setSelection method on one of the tabs (App2), then the listener on the first tab is not called. So I am guessing that it must be something to do with the fact that rendering has already taken place and then the tab bar is being re-built, that is causing this behaviour. Is this expected? Should I be coding this differently?

I hope this helps explain the problem a bit more. Thanks.

gslender
11 Oct 2008, 2:23 PM
Hi,
Thanks for taking the time to read the post, I'm sorry if it wasn't explained very well, let me try that again:
- In my onModuleLoad I am creating, amonst others things, a TabPanel (with no tabs yet) and a login Window. This gets added to the root and rendered.


be careful doing that - you should always add at least one tabitem to the panel when rendering. you can always remove it later if not needed. render problems can exist if you ask the layout to render a tabpanel with no items.



- A user then enters their username/password details in the login Window and some credentials are retrieved. This includes a set of tab names and URLs. Assume there are three tabs:
App1, App2, App3
- Then, a method is called (the code I attached) which creates the tabs from the user credentials. Each tab has a listener attached so that when it is clicked on, the browser re-directs to another application on another server. Only the current tab (let's say "App2", which is not the first tab, does not have a listener.

What is happening is that the listener on the first tab (App1) is always called first, then the listener on the selected tab (App2) is called - I mean this is happening after the tab panel is built using the code I pasted in, the user hasn't clicked on anything yet. I don't want the listener on the first tab to be called unless the user physically clicks on it.


well yes, if you listen for selection changes and you programmatically change the selection the event will be fired - if you don't want that then either a) don't unnecessarily change the selections (as you are in your for-each loop) or b) detect that this is being programmatically done (with some kind of flag) and ignore the event



If I build the same tab bar inside my onModuleLoad and use the setSelection method on one of the tabs (App2), then the listener on the first tab is not called. So I am guessing that it must be something to do with the fact that rendering has already taken place and then the tab bar is being re-built, that is causing this behaviour. Is this expected? Should I be coding this differently?
I hope this helps explain the problem a bit more. Thanks.

I'd suggest you listen to tabpanel events instead of tabitem...


Select : TabPanelEvent(container, item)
Fires after a item is selected.

see if that helps...

cheers,
grant

timefortea
13 Oct 2008, 2:45 AM
Hi there,
I modified the code so that:
- The listener was added to the TabPanel instead of each TabItem
- An "enableEvents" flag was only set to true, once the tab bar was rebuilt, with the listener only working if it was set to true.

This worked a treat for me, so thanks for all your help.

I have one other question - the mechanism of using the boolean to enable/disable events seems very similar to the enableEvents and disableEvents methods available to the TabPanel (or any Component). But I tried using them and it seemed to just disable events for good, calling enableEvents after re-building the tab bar does not seem to enable them. What are these used for?

Thanks again!