Thursday, November 13, 2008

Hide Show a Tab on Tab Navigator

Right, just a short code-snippet I'd like to share for those who have been searching for a solution for ages (like I have). I was looking for a way to hide specific tabs in a TabNavigator in Flex 3 without removing a child form the ViewStack

This is not possible by simply hiding a child in the viewstack (child.hide = true) or by setting its visibility to false (child.visible = false). 

With an easy workaround you can set the visiblity of a specific tab to false: 

tabNavigator.getTabAt(1).visible = false;

Probably more people have found this solution, but I couldn't find it on the web so here it is.

 





Bookmark and Share

17 comments:

Raj said...

Thanks for the tip. Would you mind posting how to do the same thing but by calling the tab by its id instead of its index? Thanks.

Anonymous said...

That's not good solution - everybody can switch to "hidden" tabs with keyboard. :)

Ang said...
This comment has been removed by the author.
Ang said...

If that's true, what Anonymous said, I would imagine it could be easily fixed by also setting the tab to enabled = false

Jonathan Rowny said...

@Raj:
tabs.getTabAt(tabs.getChildIndex(someTab)).visible=false;

Anonymous said...

So this leaves a hole in the tab buttons (the missing tooth look) if you hide one in the middle of your tabs. Is there some way to shift all the remaining visible tabs without creating a tab manager of your own to add/remove items in a specific order?

Steve said...

To answer the question from 'Anon' above - to solve the "hole in the tab buttons" problem, simply add the following line of code...

tabNavigator.getTabAt(1).includeInLayout = false;

Kiran T Brahaspathy said...

Great article

Marco said...

The includeInLayout was the cherry in the cake, thanks a lot!!

Anonymous said...

"hole in the tab buttons" problem solve:

tabNavigator.tabHeight = 0;

:)

Nirav said...

combination helped

tabs.getTabAt(indx).visible = false;
tabs.getTabAt(indx).includeInLayout = false;

thanks

Varad said...

Thank you very much for the code.. works very well for me.

Thanks
Varad

Varad said...

Hello,

Is it possible to have the exactly similar behavior in an Accordion.
Thanks in advance.

Regards
Varad

Chaos7703 said...

For those who want an working answer to *disabling* TabBar tabs in Flex 4.5 (probably Flex 4 also). I finally figured out a solution. It feels like a hack to me, but it's working for me. Here's a simplified example. (Note: I had to add a space after each < so that the MXML would show.)

< !-- component that has the the TabBar in it... -->

< fx:Script>
< ![CDATA[
//imports here

import mx.core.UIComponent;

//other imports

private function setTabEnabled(index:int,enabled:Boolean):void{
var theTab:UIComponent = theTabBar.dataGroup.getElementAt(index) as UIComponent;
if(theTab){theTab.enabled = enabled;}
}
]]>
< /fx:Script>

< s:TabBar id="theTabBar"
dataProvider="{viewStack}"/>

< mx:ViewStack id="viewStack">
< s:NavigatorContent label="0th Tab">
< !-- ...Content -->
< /s:NavigatorContent>
< s:NavigatorContent label="1st Tab">
< !-- ...Content -->
< /s:NavigatorContent>
< s:NavigatorContent label="2nd Tab">
< !-- ...Content -->
< /s:NavigatorContent>
< /mx:ViewStack>

< !-- rest of the component that has the the TabBar in it... -->


Then you just call `setTabEnabled(theTabIndex,trueFalse)` in an event handler related to whatever decides why the tab is, or isn't, enabled.


I *should* extend the TabBar to support this, but I've already spent enough time trying to figure it out. I'm just posting this everywhere I *thought* I found the answer.


Happy Coding =D

Chaos7703 said...
This comment has been removed by the author.
Chaos7703 said...

Addendum:
Literally two minutes after I got back to actually working, I found an "elegant" solution by skinning the TabBar.

If you apply a custom skinClass to your tab bar you can bind the tab.enabled property just like you'd expect/want.

< !-- component that has the the TabBar in it... -->

< fx:Script>
< ![CDATA[
[Bindable] private var tab2IsReady:Boolean = false;

private function checkCriteria():void{
tab2IReady = someOtherThing.isFinished;//Boolean
}
]]>
< /fx:Script>

< s:TabBar id="theTabBar"
dataProvider="{viewStack}"
skinClass="skins.CustomTabBarSkin"/>

< mx:ViewStack id="viewStack">
< s:NavigatorContent label="Tab index 0">
< !-- Your first tab's content -->
< /s:NavigatorContent>

< s:NavigatorContent label="Tab index 1" enabled="{tab2IsReady}">
< !-- Your second tab's content -->
< /s:NavigatorContent>
< /mx:ViewStack>

< !-- rest of the component that has the the TabBar in it... -->


When you type "skinClass" use the auto complete to generate the custom skin (named whatever you want).
The code will appear like below (I left out the Script tag).

< ?xml version="1.0" encoding="utf-8"?>
< !-- skins/CustomTabBarSkin.mxml
...
Adobe's copyright & doc comments
...
-->

< s:Skin
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:fb="http://ns.adobe.com/flashbuilder/2009"
alpha.disabled="0.5">

< fx:Metadata>
< ![CDATA[
/**
* @copy spark.skins.spark.ApplicationSkin#hostComponent
*/
[HostComponent("spark.components.TabBar")]
]]>
< /fx:Metadata>

< !-- optional Script tag here -->

< s:states>
< s:State name="normal" />
< s:State name="disabled" />
< /s:states>

< !--- @copy spark.components.SkinnableDataContainer#dataGroup -->
< s:DataGroup id="dataGroup" width="100%" height="100%">
< s:layout>
< s:ButtonBarHorizontalLayout gap="-1"/>
< /s:layout>
< s:itemRenderer>
< fx:Component>
< s:ButtonBarButton skinClass="spark.skins.spark.TabBarButtonSkin" />
< /fx:Component>
< /s:itemRenderer>
< /s:DataGroup>

< /s:Skin>
< --End skins/CustomTabBarSkin.mxml --?

Change:
< fx:Component>
< s:ButtonBarButton skinClass="spark.skins.spark.TabBarButtonSkin" />
< /fx:Component>
To:
< fx:Component>
< s:ButtonBarButton skinClass="spark.skins.spark.TabBarButtonSkin"
enabled="{data.enabled}" />
< /fx:Component>

Then any < s:NavigatorContent/> with its enabled property set or bound will do exactly what you expect
(be enabled when true, & disabled when false).

EL said...

This doesn't work at all for me, anyone have any code? Email to enriqueleon80@gmail.com?

Quite urgent!