|
UsingModules
Using modules with Fabrication
Featured
IntroductionFabrication provides a very simple way of communicating between modules. It uses the pipes utility as the base layer for communication. This inter-module piping is done automatically and module communication is simplified into standard PureMVC notifications. RequirementsThis feature uses the Flash Player's reflection api and when using modular applications needs an additional getClassByName method in your application's main class. This method is needed to workaround the sandboxing of getDefinitionByName. The following code must be present along with your getStartupCommand method for reflection to work. override public function getClassByName(path:String):Class {
return getDefinitionByName(path) as Class;
}Loading ModulesThe approach to loading modules differs based on its environment. For loading Flex based modules, Flex specific classes need to be used. Whereas for Flash based modules plain Loader objects are sufficient. Using Flex Module Loader for Flex ModulesFabrication provides a FlexModuleLoader for loading flex modules. This class should be used when the child module extends the FlexModule fabrication class. FlexModuleLoader extends the native ModuleLoader class so the loading api and events are the same. Loads the module, my_module.swf using the FlexModuleLoader var moduleLoader:FlexModuleLoader = new FlexModuleLoader(); moduleLoader.url = "my_module.swf"; moduleLoader.loadModule(); Using Module Manager for Flex ModulesFlex modules can also be loaded using the ModuleManager. The ModuleManager only loads the module swf. It does not instantiate the loaded swf. That needs to be done manually after the loading has completed by invoking create on the module's factory. Loads the module, my_module.swf using ModuleManager. var module:IModuleInfo = ModuleManager.getModule("my_module.swf");
module.addEventListener(ModuleEvent.READY, moduleReadyListener);
module.load();
private function moduleReadyListener(event:ModuleEvent):void {
var moduleInstance:Object = event.module.factory.create();
}Using Fabrication module loader and Fabrication AIR module loaderYou can use FabricationModuleLoader and FabricationAirModuleLoader to load module in browser or in desktop application. Both classes works similar to ModuleManager instances, but hides less important functionality from programmer. Only thing you need to do is register for ModuleEvent.READY event and retrieve module instance ( as flexModule getter ) in event handler. See example at the end of page. Using plain Loader for FlashImportant NoteThe distinction between Applications and Modules is specific to Flex. Fabrication does not make any distinction between applications and modules for Flash based applications. Any application swf that extends FlashApplication can be loaded into another FlashApplication application. Loading a flash application module can be done using the native Loader class. Loads the flash appliction module, my_module.swf using a Loader object. loader = new Loader();
loader.load(new URLRequest("my_module.swf"));Module ConfigurationModules must be configured before communication between modules can be performed. This is done by setting the router property on the module loader object. For Flex based modules this should be before loading by setting the property on the FlexModuleLoader instance. For flash based module, the property should be set on the Loader content after it has finished loading. The router for an application can be obtained by the applicationRouter property. This property is available throughout the Fabrication base classes like FabricationMediator, SimpleFabricationCommand, etc. By default a module is configured to communicate to all modules within a shell application. This behaviour can be overridden by setting the defaultRouteAddress of a module to the current application's module address. Doing so configures the module to send messages to the shell application that loaded it. For Flex modules, moduleLoader.router = applicationRouter; moduleLoader.defaultRouteAddress = applicationAddress; For Flash application based modules this needs to be done in the complete handler of the loader object used to load the module swf. private function completeListener(event:Event):void {
var content:FlashApplication = loader.content as FlashApplication;
content.router = applicationRouter;
content.defaultRouteAddress = applicationAddress;
}Sending notification between modulesCommunication between modules is done with the routeNotification method. This method is available in all the fabrication base classes like, FlexMediator, SimpleFabricationCommand, FabricationFacade, etc. The routeNotification is similar to the sendNotification method of PureMVC. However unlike sendNotification, routeNotification transports the notification across modules. The syntax of routeNotification is, routeNotification(noteName:Object, noteBody:Object, noteType:String, to:Object):void To send a notification to the default module address use, routeNotification("myNote");Like sendNotification you can specify optional noteBody, and noteType arguments. routeNotification("myNote", new Object(), "myType");To send notification to a module you use the to argument. The to argument supports the following formats.
routeNotification("myNote", null, null, "*"); // to everyone
routeNotification("myNote", null, null, "A/*); // to instances of the module A
routeNotification("myNote", null, null, "A/A0"); // to instance A0 of the module AHandling notifications from modulesThe notifications sends using routeNotification are converted to plain PureMVC notifications in the destination module. They can be mapped to commands or used with respondTo handlers, or plain handleNotification methods. Sends a messageFromModule notification to all modules routeNotification("messageFromModule", null, null, "*");Handles the messageFromModule notification that originated in another module. public function respondToMessageFromModule(note:INotification):void {
}Sending custom notification objects between modulesYou can also send custom typed notification object between modules. This is done by specifying the custom notification object as the first and only parameter of routeNotification. Handling the notification in destination module is same as with a dynamic notification. Sends a custom ModuleNotification to all modules routeNotification(new ModuleNotification(ModuleNotification.MESSAGE_FROM_MODULE)); Handles the custom ModuleNotification as a custom PureMVC notification. public function respondToMessageFromModule(note:ModuleNotification):void {
}Examples | |
Hey Darshan, Thanks for creating the gr8 utility! I am a newbie at PureMVC(mostly been playing with cairngorm) .With respect to modular sample you have ,I would want to seperate out the module as a seperate project just to keep things a little cleaner.Do you think it could pose any issues?
IMPORTANT It seems like you need to set router and defaultRouteAddress properties on the module before adding it to the display list.
You can set router and defaultRouteAddress proprties after adding it ot the display list. Simple solution:
content.initializeFabricator(); content.router = applicationRouter; content.defaultRouteAddress = applicationAddress; content.dispatchEvent( new Event( Event.ADDED_TO_STAGE ) );
I saw a line of code in the simple_routing example:
what does "SimpleModule?/#" here mean and how is it different from "SimpleModule?/"? Thank you.
Hi, belive me or not - that is mistake. Of course, it should be "SimpleModule?/`". thanks for spotting it, I should fix the example now :)
Raf -
I'm having a hell of a time trying to get modules to work properly with PopupManager?? -- can you tell me what I might be doing wrong or give an example?
I've got the main application mediator attempting to load in the widget (which is the mxml called OrderSubmit?? and a mediator of OrderSubmitMediator??):
private function loadOrderSubmitWidget():void{ if(DEBUG){Log.info(NAME + ' Load OrderSubmit module')}; var u:String = "com/investlab/mix/widgets/OrderSubmit/OrderSubmit.swf"; //loadWidget(u, orderPlaceCallback); module = ModuleManager.getModule(u); Log.debug("ALMOST"); module.addEventListener(ModuleEvent.READY, function(e:Event):void{ Log.debug("popup after"); ord = module.factory.create() as OrderSubmit; ord.width = 400; ord.height=300; PopUpManager.addPopUp(ord, FlexGlobals.topLevelApplication.stage, true); registerMediator(new OrderSubmitMediator(ord)); PopUpManager.centerPopUp(ord);The above doesn't seem to thrown an error -- but nothing is shown, so I'm definitely doing something wrong.
Usually I throw the string (u above) to a function with a callback (as above OrderPlaceCallback?
private function loadWidget(u:String, f:Function):void{ var m:FlexModuleLoader = new FlexModuleLoader(); m.router = applicationRouter; m.defaultRouteAddress = applicationAddress; m.url = u; m.addEventListener(ModuleEvent.READY, f); m.addEventListener( ModuleEvent.ERROR, loggerModuleErrorHandler ); application.addElement(m); m.loadModule(u); }the above works but I can't use it as a popup.