tags:

views:

2291

answers:

2

Hi, I've recently changed to Mate as a framework for flex. However am running into a few issues. I want to know how to dispatch events from classes generated via the methodInvoker tag.

<resultHandlers>
  <MethodInvoker generator="{LoginSuccess}" method="setCurrentUser" arguments="{[resultObject]}"/>

Then in the class I'd like to dispatch an event.

public function setCurrentUser(calUser:Object):void{
  if(calUser != null){
   Model.instance.currentUser = calUser as CalUser;
   loadOnlineCalendars(Model.instance.currentUser);
  }
 }

 public function loadOnlineCalendars(calUser:CalUser):void{
  for(var i:int = 0 ; i<calUser.calConnectors.length; i++){//logic here
   dispatchEvent(new CalConnectorEvent(calUser.calConnectors as CalConnector,CalConnectorEvent.LOAD_ONLINE_CALENDAR_EVENT,true));
  }
 }

The problem is I can't seem to be able to catch the event in the eventMap or even in the application root.

If anyone has any experience with Mate, I'd appreciate some pointers. Perhaps I'm doing this all wrong. I just want to get a result from the server - look at the result and depending on the result contact the server again. Should be quite simple.

Event Map:

            <resultHandlers>
            <MethodInvoker generator="{LoginSuccess}" method="setCurrentUser" arguments="{[resultObject]}"/>
            <ServiceResponseAnnouncer type="result"/>

            </resultHandlers>
            <faultHandlers>
            <ServiceResponseAnnouncer type="fault"/>

            </faultHandlers>
    </RemoteObjectInvoker>

+3  A: 

After some digging around here, I found that you can't call an event from a non-view class. That forum post describes the elegant solution, and also offers a quick workaround:

Application.application.dispatchEvent(new CalConnectorEvent(calUser.calConnectors as CalConnector,CalConnectorEvent.LOAD_ONLINE_CALENDAR_EVENT,true));

But check out the forum post- there's a lot of meat in there.

Mike Sickler
Thanks for that Mike. I've added the closing tag. So should I be able to listen to events dispatch from classes generated via the methodInvoker tag from within the same map?
Nice one. That makes sense. I've used that style before but when sending an event from an item renderer. Anyway, thanks.
I wrote that forum post (#2 from the top) and this solution is an ugly hack and I strongly discourage anyone to use it. Look for my answer to this question, or read the full forum post, where you will find a more robust solution.
Theo
You're right, Theo- I should have been more clear in the answer that the code block above is a quick-and-dirty hack.
Mike Sickler
Thanks a lot mate... was struggling for 4 hours to figure out this issue.
+4  A: 

The way it's usually done is to inject the event map's dispatcher into the object:

<MethodInvoker generator="{MyClass}" method="someMethod" arguments="{[a, b]}">
  <Properties dispatcher="{scope.dispatcher}"/>
</MethodInvoker>

The inner Properties tag sets properties on the object being created by the MethodInvoker, and the properties are guaranteed to be set before the method is invoked.

The class obviously needs to have a public property called dispatcher (or whatever name you prefer) for this to work. To dispatch events that you want to listen for in the event map call dispatcher.dispatchEvent(...).

If the object created by the MethodInvoker will be used more than once, if it's a manager, say, the common idiom is to create it using an ObjectBuilder is an event handler block that gets triggered by FlexEvent.INITIALIZE:

<EventHandlers type="{FlexEvent.INITIALIZE}">
  <ObjectBuilder generator="{MyClass}" constructorArguments="{scope.dispatcher}"/>
</EventHandlers>

In this example the event dispatcher is injected as a constructor argument, but you can use an inner Properties tag just as with MethodInvoker.

Theo