As Flex Architects / Team Leads can attest (at least those of us who do the proper preparation for a project), choosing an architecture to base your code upon isn’t an easy task since many good ones are out there, however each is like a relationship that leaves just a little off the table to be truly a desirable solution. However as with any framework worth it’s work, most of them are highly extensible without the need to modify the original to achieve the characteristics you need / want.

RobotLegs: Mediating sub-content to a Spark NavigatorContent pane.
Turns out there is a ‘bug’ and/or limitation when using the spark-based layout framework, and thankfully it’s a relatively easy one to over come. It has to do with the <s:NavigatorContent /> and how those children are built according to it’s creationPolicy as set by an appropriate container (TabNavigator, Accordion, and so on). Because the mediator is triggered on the FlexEvent.CREATION_COMPLETE event, it doesn’t take into consideration that while additional containers will be put on the stage, their containing children will not be instantiated since it’s part of the deferred process. This leaves the mediator in ‘limbo’ land since we obviously want to setup the user gestures for all the guts of the container (combos, buttons, data grids, etc).

There is a way around this and it looks like this. Essentially the solution is to capture / override the creationcomplete handler, and determine if it’s an INavigatorContent interface to which we then check on the contentChildrenCreated flag. If this is false (as it will be the first time around), we then defer and wait for the secondary CONTENT_CREATED event to then recycle back through the creationcomplete handler and allow the onRegister() to be triggered when all the content is actually created.

package
{

import flash.events.Event;

import mx.core.INavigatorContent;
import mx.core.UIComponent;
import mx.events.FlexEvent;

import org.robotlegs.mvcs.Mediator;

/**
* This mediator is intended for INavigatorContent / Spark.NavigatorContent
* views – when created unless it is the current visible item based on it’s
* contentCreationPolicy – it will only create the outer shell of the view.
*
* So here we check the associated view and if it is deferred – we halt
* the onRegister process until it has triggered the FlexEvent.CONTENT_CREATION_COMPLETE
* event.
*/
public class NavigatorContentMediator extends Mediator
{

public function NavigatorContentMediator()
{
super();
}

override public function onRemove():void
{
super.onRemove();
view.removeEventListener(FlexEvent.CONTENT_CREATION_COMPLETE, onContentCreationComplete);
}

override protected function onCreationComplete(event:Event):void
{
if (view.deferredContentCreated) super.onCreationComplete(event);
else
{
view.removeEventListener(event.type, onCreationComplete);
view.addEventListener(FlexEvent.CONTENT_CREATION_COMPLETE, onContentCreationComplete);
}
}

protected function onContentCreationComplete(event:FlexEvent):void
{
view.removeEventListener(FlexEvent.CONTENT_CREATION_COMPLETE, onContentCreationComplete);
super.onCreationComplete(event);
}

/**
* A rare case where we want a private property to the view – this allows us
* to ensure it’s of the interface we want without enforcing the same interface
* in super mediators – allowing them to type cast a protected or private property
* as the concrete view it mediates.
*/
private function get view():INavigatorContent
{
return getViewComponent() as INavigatorContent;
}

}
}