Blocking TabBar Click/Change Events
12.15.2008One scenario that often presents itself when developing a Flex application is blocking users from navigating away from the current view. You might want to do this if the user’s form data is incomplete or if data has changed and you want to ensure they want to discard or save their changes.
When the TabBar comes into play, blocking tab changes isn’t always straightforward. The TabBar doesn’t dispatch any type of TabChanging event that can be canceled. Nothing else is really offered in the way of blocking the action either. To make matters worse, a click on a tab in the tabbar actually dispatches two different click events, one of which is a “simulated click trigger event.”
My purpose isn’t to go into the shortcomings of the TabBar component or its inner workings. Instead, I’ll offer the BlockableTabBar for your use:
package com.mediarain.controls { import flash.events.MouseEvent; import mx.core.mx_internal; import mx.controls.Button; import mx.controls.TabBar; use namespace mx_internal; /** * Extends the functionality of TabBar by exposing a <code>condition</code> function property * that will be evaluated before the tab changes. The behavior will only be allowed if the * condition is met. * * @author Aaron Hardy - http://aaronhardy.com */ public class BlockableTabBar extends TabBar { /** * The condition that allows/disallows the click event to proceed. This must be a * function that returns a Boolean value. */ public var condition:Function; /** * @private * A flag indicating whether the tabbar's simulated click has been blocked due to the * blocking condition failing. This is used later when the real click comes through * so it can also be blocked without evaluating the condition again. This not only * cuts down processing but the developer can show an alert within the condition * without it being displayed multiple times. */ private var simulatedClickBlocked:Boolean = false; /** * Adds a click handler to intercept click events. */ public function BlockableTabBar() { super(); addEventListener(MouseEvent.CLICK, clickInterceptor, true); } /** * @private * Intercepts click events on the tab bar and evaluates whether the condition has * been met to allow the tabs to be changed. If the condition is not met, the event * is ignored. The simulatedClickTriggerEvent handling and the need for the two * conditions is due to the functinality in the underlying tabbar architecture. */ protected function clickInterceptor(event:MouseEvent):void { if (simulatedClickTriggerEvent && event.target is Button && condition != null && !condition()) { event.stopImmediatePropagation(); event.preventDefault(); simulatedClickBlocked = true; } else if (!simulatedClickTriggerEvent && simulatedClickBlocked) { event.stopImmediatePropagation(); event.preventDefault(); simulatedClickBlocked = false; } } } }
The idea here is that any mouse click on a tab is captured on the “capture” event phase. In other words, we’re intercepting the mouse click before the TabBar can get to it and act on it. In order for the event to continue on its way, we will execute the “condition” property, which is a function that returns a boolean value. This property is the one you as a developer will set and should be a reference to a function that contains the logic evaluating whether the user should be allowed to move away from the current tab. If the function returns a value of true, it will let the event pass on and the the user will be taken to the clicked tab as usual. If the function returns a value of false, it will prevent the event from continuing on and will prevent the user from leaving the current tab.
If you’re dealing with a TabNavigator class instead of the TabBar class, my comrade Nate has a post that could help in that respect. See his post: Preventing the TabNavigator from changing tabs when one is clicked.
Hope that helps! Let me know if you have bugs, suggestions, or questions.
Tags: block click, capture event, Flex, preventDefault(), stopImmediatePropagation(), TabBar


[...] for a good solution to prevent a TabBar from changing instead of the TabNavigator, check out Aaron Hardy’s blog. He used it in a project we did together and it worked [...]