This blog post is related to My LFPUG Presentation about Mate blog post.
This is the eigth of a series of gradually more complex examples on how to use Mate. If you haven’t done it yet you should have a look first at our previous examples: #1, #2, #3, #4, #5, #6, and #7.
In our two previous examples, we saw how easy it was to handle communication between the application and its subcomponents, without mix-up between events intended to be listened by the whole application and events required only at the subcomponent level. But how would Mate hold up with with even looser subcomponents, of the kind that are loaded on demand and are not a concrete part of our main application, namely Modules?
I’m sure you know already it holds up pretty well, but let’s see how it does that:
The great thing here is that we didn’t change much between this example and our previous Reset Countdown. Basically, aside moving Counter.mxml and SubCounter.mxml into a new modules package and changing Counter.mxml from a Panel into a Module, that’s about it:
Demo #8: src/modules/Counter.mxml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 | <?xml version="1.0" encoding="utf-8"?> <mx:Module xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" width="264" height="380" xmlns:maps="maps.*" xmlns:modules="modules.*"> <mx:Script> <![CDATA[ import Events.CounterEvent; [Bindable] public var globalAmount : int = 0; [Bindable] private var subTotal : int = 0; [Bindable] private var amount : int = 0; private var _counterTitle : String = "Counter Title"; [Bindable] public function get counterTitle() : String { return _counterTitle; } public function set counterTitle( v : String ) : void { _counterTitle = v; } public function increaseSubTotal( event : CounterEvent ) : void { ++subTotal; } public function decreaseSubTotal( event : CounterEvent ) : void { --subTotal; } public function reset( event : CounterEvent ) : void { subTotal = 0; } ]]> </mx:Script> <maps:SubEventMap dispatcher="{this}"/> <mx:Panel width="264" height="380" title="{counterTitle}" layout="absolute"> <mx:Label x="27" y="10" text="Global Amount:"/> <mx:Label x="121" y="10" text="{globalAmount}"/> <modules:SubCounter y="64" horizontalCenter="0" borderStyle="inset"> </modules:SubCounter> <modules:SubCounter y="208" horizontalCenter="0" borderStyle="inset"> </modules:SubCounter> <mx:Label x="63" y="35" text="Subtotal:"/> <mx:Label x="124" y="35" text="{subTotal}"/> </mx:Panel> </mx:Module> |
Don’t forget to declare Counter.mxml as a Flex Module in your project’s properties and of course update all your references to Counter and SubCounter from views to modules (i.e. import view.Counter => import modules.Counter).
And then, all you need to do is to change your addCounterButton_clickHandler method in MainView.mxml from a simple Class instantiation into a ModuleLoader loader:
Demo #8: src/views/MainView.mxml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 | <?xml version="1.0" encoding="utf-8"?> <mx:Panel xmlns:mx="http://www.adobe.com/2006/mxml" width="860" height="600" title="{mainTitle}" layout="absolute" xmlns:views="views.*"> <mx:Script> <![CDATA[ import mx.modules.ModuleLoader; import Events.CountdownEvent; import Events.CounterEvent; [Bindable] public var globalAmount : int = 0; [Bindable] public var isCountdownRunning : Boolean; [Bindable] private var numCounters : int = 0; [Bindable] private var mainTitle : String = "MainView"; protected function buttonIncrease_clickHandler( event : MouseEvent ) : void { dispatchEvent( new CounterEvent( CounterEvent.INCREASE_GLOBAL )); } protected function buttonDecrease_clickHandler( event : MouseEvent ) : void { dispatchEvent( new CounterEvent( CounterEvent.DECREASE_GLOBAL )); } protected function addCounterButton_clickHandler( event : MouseEvent ) : void { var moduleLoader : ModuleLoader = new ModuleLoader(); moduleLoader.url = "modules/Counter.swf"; mainTile.addChild( moduleLoader ); ++numCounters; } protected function deleteCounterButton_clickHandler( event : MouseEvent ) : void { var displayObject : DisplayObject = mainTile.getChildAt(mainTile.numChildren - 1); ModuleLoader( displayObject ).unloadModule(); mainTile.removeChild( displayObject ); --numCounters; } public function updateTitle( event : CountdownEvent ) : void { mainTitle = "MainView (" + event.countdown + ")"; } protected function countdownButton_clickHandler( event : MouseEvent ) : void { if ( isCountdownRunning ) { countdownButton.label = "START COUNTDOWN"; dispatchEvent( new CountdownEvent( CountdownEvent.STOP_COUNTDOWN )); } else { countdownButton.label = "STOP COUNTDOWN"; dispatchEvent( new CountdownEvent( CountdownEvent.START_COUNTDOWN )); } } ]]> </mx:Script> <mx:Label text="Global Amount:" x="28" y="16"/> <mx:Label text="{globalAmount}" x="124" y="16"/> <mx:Tile id="mainTile" left="10" right="10" top="82" bottom="10"> </mx:Tile> <mx:Button id="buttonIncrease" x="68" y="34" label="+" click="buttonIncrease_clickHandler(event)"/> <mx:Button id="buttonDecrease" x="140" y="34" label="-" click="buttonDecrease_clickHandler(event)"/> <mx:Button id="addCounterButton" x="614" y="31" label="Add Counter" click="addCounterButton_clickHandler(event)"/> <mx:Button id="countdownButton" x="366" y="31" label="STOP COUNTDOWN" click="countdownButton_clickHandler(event)"/> <mx:Button id="deleteCounterButton" x="716" y="31" label="Delete Counter" enabled="{numCounters > 0}" click="deleteCounterButton_clickHandler(event)"/> </mx:Panel> |
And yet our application keeps behaving as it always did. Isn’t that great? It is, it is, but the example is still not perfect: the views are now separated from the main application, but the logic is still part of it and there are references to the modules’ classes all around in the main application. We can clearly decouple a bit further and we’ll see how in our next part: #9 Modules Example (pt 2)
Related posts:
- Mate examples: #9 Modules Example (pt 2) This is the ninth of a series of gradually more...
- Mate examples: #6 Reset Countdown (pt 1) This blog post is related to My LFPUG Presentation about...
- Mate examples: #5 LocalEventMap This is the fifth of a series of gradually more...
- Mate examples: #7 Reset Countdown (pt 2) This is the seventh of a series of gradually more...
- Mate examples: #4 Counters created dynamically This is the fourth of a series of gradually more...
Related posts brought to you by Yet Another Related Posts Plugin.

Subscribe
/Mate_example7.png)



Excellent examples, and I look forward to the next part. Got a couple of questions in regards to Modules, Flex and Cairngorm.
When using Modules, what is the best way to manage more than one of the same entity from the main application to the Module. For example, I have a list of users, the user clicks on a user, I want it to load that user in a User module, before closing that User module, I want to load a different user from the main application. Single Main -> Multiple Sub Application properties are o.k, but Multiple Main -> Single / Multiple Sub Application properties???. I can do it by setting the property when I create the Module, but this is coupling? is there a better way to do it?
My latest thought is to have a more generic identifier, that can be used so that the module does the hard work of getting information about the identified entity, disconnecting it from the main application in a way, but what if that entity changes in my main application?
Cheers
Gareth.
Well, creating the Module is already coupling somehow so I don’t really see what’s wrong in affecting some properties along the way. Don’t also forget that if you want to address a specific subcomponent from the main application you can pass a property like targetSubComponent along with your event for example. Every sub-component will catch it but you can then easily check which specific one is being targeted.
Have a look on the second example as well, it might give you some other ideas on how to deal with your problem.