Understanding TabSheet.replaceComponent

Hi guys!

I have a TabSheet in my app, and a custom window manager handling the navigation. Initially I put some content to every tab, and change them when user navigates to a different view (i.e. opens a single record from a search page).

What worries me is the behaviour of the TabSheet when navigation happens inside a Tab. When I replace the current view with the new one, the TabSheet.replaceComponent also changes (creates a new) the Tab component. Why is that necessary?

That functionality breaks my view stack, because I can’t use the Tab objects as identifiers (in maps etc.) because they change although the user has not actually changed the Tab.

Hi Ville,

This is probably due to how the TabSheet is implemented. If I remember correctly, the TabSheet contains no metadata pertaining to the different tabs (i.e. which tab has what component(s), tab caption, etc), but uses the components that are added to the TabSheet as tabs directly. Whew, what a sentence!

In other words the TabSheet has no internal tabs, only a set of components and uses component.getCaption() for the tab headers. This is why you get different identifiers when you use TabSheet.replaceComponent() – you actually replace the
tabs
themselves.

HTH,
/Jonatan

The current version of TabSheet (since 6.0 if I remember correctly) does have a separate concept and object for the tabs unlike older IT Mill Toolkit versions.

If both the old and the new component are in the same TabSheet, replaceComponent() should simply swap the positions of the tabs and keep the identities of the Tab objects. However, if the replacing component is not in the current TabSheet, the TabSheet doesn’t know whether there is a Tab object associated with it somewhere else or not. Therefore, a new Tab instance is created for it. As replaceComponent() comes from an interface, it cannot return the new Tab object, but it is possible to obtain a reference to it with getTab().

When removing a component from a TabSheet, the corresponding Tab object is discarded, which makes sense - otherwise, memory leaks would occur etc.

And how can you replace the content of a tab easily?

Here is my code:



final VerticalLayout initialLayout = new VerticalLayout();
final TabSheet.Tab tab = tabs.addTab(initialLayout, "View");
tab.setClosable(true);
tabs.setSelectedTab(initialLayout);


// Later, I want to replace the content of the "View" tab by something else - called newTabComponent

final Component currentTabComponent = tabs.getSelectedTab();
replaceComponent(currentTabComponent, newTabComponent);    

The problem is that the new component is added below the tabsheet. (outside the tab sheet!)

well, ok. replaceComponent was called on the wrong component. Adding “tab.” in there fixed the issue :slight_smile: