This tutorial explains how to get started with Mate. As an example, we'll create a stock quote retrieval screen which sends the quote symbol to the server, receives the current price and stores it in the model for the view to show.
All Mate projects must have:
- One or more events (custom or built-in)
- One or more Event Maps
Typically, the basic steps to create a Mate project are:
- Add the compiled framework code to your project (Mate.swc).
- Create a file that will be the EventMap.
- Include the event map in your main Application file.
- Create a custom event.
- Somewhere, dispatch that event.
- Add EventHandlers in your event map that listen for the event type you dispatched.
- Execute some actions inside the EventHandlers block (ie: call the server, store data, etc).
- Repeat 4-7 for every event you need.
Get the source for this tutorial
Creating a new project
In Flex Builder, create a new Flex project called "StockQuotesExample". Let the main source folder be "src" (default folder).
In the libs folder it creates, place the compiled framework SWC (Mate.swc). This will let you use all Mate classes and tags.
The Quote custom event
Every Mate project is driven by events. In the stock quote example, when the user enters the stock symbol and clicks on the "Get Quote" button, we'll create a new event containing that information that will be sent to the server. Therefore, we need to create a custom event to indicate that the user wants to submit the symbol and retrieve the current price.
Our event will be very simple and it will contain one property: the symbol.
package com.asfusion.mate.stockQuoteExample.events
{
import flash.events.Event;
public class QuoteEvent extends Event
{
public static const GET: String = "getQuoteEvent";
public var symbol : String;
public function QuoteEvent(type:String, bubbles:Boolean=true, cancelable:Boolean=false)
{
super(type, bubbles, cancelable);
}
}
}
The code above assumes this event is contained within the package: com.asfusion.mate.stockQuoteExample.events
The event also contains a constant that we will use to specify the event type. One event can specify more than one event type.
We also make this event bubble up by default (the second argument of the constructor). Otherwise, we will need to remember to specify it when we instantiate it.
Creating the UI
The user interface will only need a text input and a button:

Dispatching the QuoteEvent
When the user clicks the Get Quote button, we'll create the QuoteEvent and dispatch it:
import com.asfusion.mate.stockQuoteExample.events.QuoteEvent;
private function getQuote() : void {
var quoteEvent:QuoteEvent = new QuoteEvent(QuoteEvent.GET);
quoteEvent.symbol = symbolInput.text;
dispatchEvent(quoteEvent );
}
The Event Map
The EventMap is where we place the handlers for all the events the application creates (there could be more than one event map, though).
To add the event map, we need to create a new MXML file, with name "MainEventMap". This component must extend from EventMap. At this point, the event map would be empty and it should look like this:
<?xml version="1.0" encoding="utf-8"?>
<EventMap
xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns="http://mate.asfusion.com/">
</EventMap>
Note: we use no namespace for http://mate.asfusion.com so that we don't have to add it to every tag in the event map. You can copy the code above to your file as a starting point.
We'll add the event map to our main Application file:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" xmlns:maps="com.asfusion.mate.stockQuoteExample.maps.*">
<maps:MainEventMap />
</mx:Application>
Setting up debugging
In order to know whether our event map is receiving the events that get dispatched, we add the debugger tag to the event map:
<Debugger level="{Debugger.ALL}" />
The EventMap so far:
<?xml version="1.0" encoding="utf-8"?>
<EventMap xmlns:mx="http://www.adobe.com/2006/mxml" xmlns="http://mate.asfusion.com/">
<Debugger level="{Debugger.ALL}" />
</EventMap>
Listening for QuoteEvent.GET
In our event map, we will listen for the quote event so that we can send the request to the server.
We'll add an EventHandlers tag that will specify the event type we are listening to. We'll also set the debug attribute to true so that we can see when the handlers run in the debugging output window.
<EventHandlers type="{QuoteEvent.GET}" debug="true">
</EventHandlers>
At the top of the event map we'll need to import the event class.
<mx:Script>
<![CDATA[
import com.asfusion.mate.stockQuoteExample.events.QuoteEvent;
]]>
</mx:Script>
Inside this EventHandlers block, we'll place the actions we want to perform when the event is dispatched. In this case, we would like to make a server call, for which we'll use the RemoteObjectInvoker tag. Assuming the service in a folder called stockQuoteExample and it is called QuoteService, you will specify the call as follows:
<RemoteObjectInvoker destination="ColdFusion" source="stockQuoteExample.QuoteService"
method="getQuote"
arguments="{event.symbol}"
debug="true">
</RemoteObjectInvoker>
We are calling the method getQuote on that service and sending the symbol coming from the event as an argument of the remote method call.
Handling the server result
The server returns a numerical value with the stock's current price. We will handle that result inside the RemoteObjectInvoker's resultHandlers and call the function "storeQuote" on the QuoteManager class.
<EventHandlers type="{QuoteEvent.GET}" debug="true">
<RemoteObjectInvoker destination="ColdFusion"
source="stockQuoteExample.QuoteService"
method="getQuote"
arguments="{event.symbol}"
debug="true">
<resultHandlers>
<MethodInvoker generator="{QuoteManager}"
method="storeQuote" arguments="{resultObject}"/>
</resultHandlers>
</RemoteObjectInvoker>
</EventHandlers>
If you have shared data that many views will access, you may want to create a "model". In this simple example, you don't really need a model, but because it is something you will usually need, we'll add it anyway.
Inside the resultHandlers, we are using a MethodInvoker to create an instance of QuoteManager (if it doesn't already exist) and then call the method storeQuote. Inside the resultHandlers, we can access the result coming from the server, which we can pass as the argument of the method call.
Creating our Model, the QuoteManager
The QuoteManager will handle the business logic that has to do with quotes. It will also store the current symbol's quote so that it can be used by views. In the previous section, we were calling the method storeQuote(price) that stores the value of the current symbol's price. The class definition for this manager is:
package com.asfusion.mate.stockQuoteExample.business
{
public class QuoteManager
{
[Bindable]
public var currentPrice:Number;
public function storeQuote(price:Number):void {
currentPrice = price;
}
}
}
Ideally, the currentPrice property would be read-only instead of public. But in order to do that and still making it bindable, we will need to do some additional work.
Also, when the method storeQuote is called, we can execute any necessary business logic.
Showing the current price value in the view
So far, when the event is dispatched, we make a service call, the server returns the current price and that price is stored in the QuoteManager. But now we need to be able to show that value in the view.
In the view where we want to show the price, we'll add a property:
[Bindable]
public var price:Number;
and then show that number anywhere in the view we want, for example, in a Label:
<mx:Label text="Price: {price}" />
That's all we need in the view.
Getting the current price from the model Manager to the view
But how does the view get this variable populated from the price stored in the QuoteManager?
In our event map, we'll add another set of tags. These tags will assign a property on the model to a property on the view, and because the property on the model is bindable, the view will always get the most current value.
<Injectors target="{QuotePanel}">
<PropertyInjector targetKey="price" source="{QuoteManager}" sourceKey="currentPrice" />
</Injectors>
When you add this, make sure you have all the necessary import statements at the top of your event map.
Event-Service call-Model Manager-View
View the example running, view the source and download the example in the example page.
There is a small error in the code for the main application file. The name space is declared as: xmlns:maps="com.asfusion.mate.loginExample.maps.*".
It should be: xmlns:maps="com.asfusion.mate.stockQuoteExample.maps.*"
Thanks for pointing that out. It's fixed now. :)
The Command pattern is very simple to implement by using the MethodInvoker tag making it call execute. We have a tag that actually does that: CommandInvoker
What neither the tag nor Cairngorm does is to implement the unexecute function necessary to "undo". That can be done with the MethodInvoker tag too.