views:

262

answers:

2

Assuming the following pattern:

someObjectInstance.addEventListener(MyDisplayObject.EVENT_CONSTANT, _handleMyEvent);


private function _handleMyEvent( event:Event = null ):void
{
  // Event handler logic...
}

If I wanted to add a required parameter to the handler function am I able to do this and still use a "generic" event and event listener? Or am I correct in assuming that I need to create a custom event class that has the parameter in it and reference that through the event object passed into the handler function?

To phrase this another way... If I have a handler function that looks like this:

private function _handleMyEvent( data:Object, event:Event = null ):void
{
  if (data == null)
  {
      return;
  }
  // Event handler logic...
}

Then what does the addEventListener function need to look like? Is there a more advanced syntax? Is there a way to do this with closures?

Looking for a clear code example and/or documentation reference. Just trying to understand if I absolutely have to override the generic Event class in this scenario.

+2  A: 

If you need custom data to travel with your event, yes, you need to create a custom event class.

Here's a simple example:

package {
    import flash.events.Event;

    public class ColorEvent extends Event {
        public static const CHANGE_COLOR:String = "ChangeColorEvent";

        public var color:uint;

        public function ColorEvent(type:String, color:uint, bubbles:Boolean = false, cancelable:Boolean = false) {
            this.color = color;
            super(type, bubbles, cancelable);
        }

        override public function clone():Event {
            return new ColorEvent(type, color, bubbles, cancelable);
        }
    }
}

Please note that the clone method is NOT optional. You must have this method in your custom class for your event to ever be re-broadcast properly (say when one object gets the event, and then re-dispatches it as it's own).

Now as for dispatching the event, that would work like this (obviously this code would go in a method of class that extends EventDispatcher).

dispatchEvent(new ColorEvent(ColorEvent.CHANGE_COLOR, 0xFF0000));

And finally, to subscribe to the event:

function onChangeColor(event:ColorEvent):void {
    trace(event.color);
}

foo.addEventListener(ColorEvent.CHANGE_COLOR, onChangeColor);
Branden Hall
Ok thanks for the response. That is what I suspected. Just wanted to make sure that there wasn't some other way of passing data around with the generic Event. Just as general rule do you find it useful to create custom "generic event with data" that passes around a generic object or do you find it better to create more specific events for specific purposes? Part of me feels that code reuse can come from more generic events. But another part of me wonders if there is more utility derived from the specificity of custom events. More code to write but narrower scope to focus on if there is a bug.
Gordon Potter
I try to keep my events as specific as possible. The reason for this is that they act as a kind of marker in the code for me later. If I'm using XEvent I know it has something to do with X class so it's easier to remember what code does later.
Branden Hall
In my case I created a custom event class that can take an array of parameters and just customize the event name if I want to make it unique. I've actually found in the long-run that minimal, more generic event names are easier to maintain than specific ones. Fewer headaches since the object handling the events usually provides more than enough context for you to understand the code. But there's no wrong answer. Just style preference.
Glenn
+1  A: 

There is a way of passing custom data to the handler method without creating a custom event.

private function test() {
    var data : SomeObject = new SomeObject;
    var a:SomeEventDispatcher = new SomeEventDispatcher();
    a.addEventListener(Event.COMPLETE, handle(data));   
    a.dispatchCompleteEvent();
}

private function handle(data : SomeObject) : Function {
    return function(e : Event) : void {
       IEventDispatcher(e.target).removeEventListener(Event.COMPLETE, arguments.callee);
       trace(e + ", " + data);
    };
}
maxmc
Interesting code example. Thanks.
Gordon Potter