The standard Cairngorm event handling approach enforces MVC
architecture by assuming the results of any event processing are
primarily used to update a model that the views are bound to.
Viewhelpers and ViewLocators are provided for other situations but
they only add confusion and further abstraction. Besides, I still
haven't figured out how to make them work.
The architecture described below uses the standard Cairngorm process
of creating a CairngormEvent object and mapping the event to a
Command via the FrontController. The Command executes whatever
operations are needed, and if waiting for results from an
asynchronous data service, implements IResponder to handle result
and fault events.
So far, this is the same. What is different is in the event object –
it contains placeholders for those result and fault event objects,
and then re-instantiates itself as its own event result or fault and
dispatches the event with the result and fault payloads attached, so
any class that is listening for it can act on it.
This leverages the singleton CairgormEventDispatcher as a mediator
for a publish-subscribe event model on the responder end of the
Command class. No need for viewhelpers – if the view wants to handle
the result, it just listens for it. On the same token, if the model
wants to update itself – it just listens for the result event as
well. Also, by making the event's type (event name) dynamic, you can
reuse the same class without having separate event classes for
sending requests and receiving results and faults. If there
are no data services involved, the execute() function can invoke the
event's result or fault handlers directly.
Sample Implementation – just substitute your class names for the
word "sample" for each event class and corresponding command class
that you implement.
/*** Event Object ***/
package
{
import com.adobe.cairngorm.control.CairngormEventDispatcher;
import com.adobe.cairngorm.control.CairngormEvent;
import mx.rpc.events.ResultEvent;
import mx.rpc.events.FaultEvent;
public class SampleEvent extends CairngormEvent
{
public static const EVENT_SAMPLE:String = "event_sample";
public static const EVENT_SAMPLE_RESULT:String
= "event_sample_result";
public static const EVENT_SAMPLE_FAULT:String
= "event_sample_fault";
public var resultEvent:ResultEvent;
public var faultEvent:FaultEvent;
// public var ...other properties or value objects...
public function SampleEvent(eventName:String)
{
super( eventName );
}
public function handleResult():void
{
var se:SampleEvent = new SampleEvent
(SampleEvent.EVENT_SAMPLE_RESULT);
se.result = this.result;
CairngormEventDispatcher.getInstance().dispatchEvent( se );
}
public function handleFault():void
{
var se:SampleEvent = new SampleEvent
(SampleEvent.EVENT_SAMPLE_FAULT);
se.fault = this.fault;
CairngormEventDispatcher.getInstance().dispatchEvent( se );
}
}
}
/*** View – Dispatcher ***/
Private function somethingHappened(event):void
{
Var se:SampleEvent = new SampleEvent(SampleEvent.EVENT_SAMPLE);
// populate other event or value object properties as defined...
CairngormEventDispatcher.getInstance().dispatchEvent( se );
}
/*** View – Listener for Result ***/
Private function init():void
{
CairngormEventDispatcher.getInstance().addEventListener
(SampleEvent.EVENT_SAMPLE_RESULT, myHandler);
}
/*** Fault Handler – Listener for Fault ***/
Private function init():void
{
CairngormEventDispatcher.getInstance().addEventListener
(SampleEvent.EVENT_SAMPLE_FAULT, myHandler);
}
/*** Command Class ***/
package
{
import com.adobe.cairngorm.control.CairngormEventDispatcher;
import com.adobe.cairngorm.control.CairngormEvent;
import com.adobe.cairngorm.commands.Command;
import mx.rpc.IResponder;
import mx.rpc.events.ResultEvent;
import mx.rpc.events.FaultEvent;
// import your event class
import com.whatever.events.SampleEvent;
public class sampleCommand implements Command, IResponder
{
private var se:SampleEvent; // instantiate at class level for
use by all responder functions
public function execute( event:CairngormEvent ):void
{
se = event as SampleEvent;
var delegate:GetSomeDataDelegate = new GetSomeDataDelegate(
this );
delegate.getSomeData( se.someParameter );
}
public function result( data:Object ):void
{
se.result = data as ResultEvent;
se.handleResult();
}
public function fault( info:Object ):void
{
se.fault = info as FaultEvent;
se.handleFault();
}
}
}