Skip to main content
Participant
December 7, 2012
Question

passing custom events between modules through parent application

  • December 7, 2012
  • 1 reply
  • 611 views

I have created a custom event that I want to use to pass a string between two modules.  The event looks like this:

    package com.mypackage.events

    {

          import flash.events.Event;

 

          public class ThumbDeleteEvent extends Event

          {

                    public static const THUMBS_DELETED:String = "thumbsDeleted";

 

                    public var files:String;

 

                    public function ThumbDeleteEvent(type:String, files:String)

                    {

                    super(type);

                    this.files = files;

                    }

 

                    // Override the inherited clone() method.

                    override public function clone():Event {

                    return new ThumbDeleteEvent(type, files);

                    }

 

          }

    }

In one module I dispatch the event like so:

    parentApplication.dispatchEvent(new ThumbDeleteEvent("parentApplication.thumbsDeleted", files));

and in another module I listen for the event like so:

    public function init():void {

                    parentApplication.addEventListener("parentApplication.thumbsDeleted", onThumbsDelete);

                    }

if I use ThumbsDeleteEvent as the type passed in to the listener function like this:

 

    public function onThumbsDelete(evt:ThumbDeleteEvent):void{

           trace("thumb delete event for thumbs: "+evt.files);

    }

I get the following error:

    TypeError: Error #1034: Type Coercion failed: cannot convert  com.mypackage.events::ThumbDeleteEvent@26748a31 to com.mypackage.events.ThumbDeleteEvent.

if I just use Event as the type passed in to the listener function like this:

    public function onThumbsDelete(evt:ThumbDeleteEvent):void{

          if(evt is ThumbDeleteEvent){

                    trace("thumb delete event for thumbs: "+(evt as ThumbDeleteEvent).files);

          }else{

                    var type:XML = describeType(evt);

                    trace(type.toXMLString());

          }

    }

It works but does not think it is a ThumbDeleteEvent type class (it hits the else statement) the xml output of describe type says its type is:

    type name="com.mypackage.events::ThumbDeleteEvent"

What is going on here?  If I put a breakpoint in the debugger it says the event is a ThumbDeleteEvent and I can see the files parameter and its right???

This topic has been closed for replies.

1 reply

sinious
Legend
December 7, 2012

Here's a simple custom event that supports extra data that I use for just about everything:

AppEvent.as:

package

{

    import flash.events.Event;

    public class AppEvent extends Event

    {

        public static const APP_EVENT:String = "appevent";

        public var params:Object;

        public function AppEvent(type:String, params:Object, bubbles:Boolean = false, cancelable:Boolean = false)

        {

            super(type, bubbles, cancelable);

            this.params = params;

        }

        public override function clone():Event

        {

            return new AppEvent(type, this.params, bubbles, cancelable);

        }

        public override function toString():String

        {

            return formatToString("AppEvent", "params", "type", "bubbles", "cancelable");

        }

    }

}

Say I had 2 classes (ClassA and ClassB). If ClassA loads an instance of ClassB inside it, it'd look like this to communicate (doing it by memory, but you get the idea):

ClassA.as:

package

{

     import flash.display.Sprite;

     import AppEvent;

     import ClassB;

     public class ClassA extends Sprite

     {

          private var _classB:ClassB = new ClassB();

          public function ClassA()

          {

               addChild(_classB);

               // listen for events dispatched in ClassB

               _classB.addEventListener(AppEvent.APP_EVENT, _handler);

               // How you'd dispatch to ClassB:

               // _classB.dispatchEvent(new AppEvent(AppEvent.APP_EVENT, { change:"some data",more:123,data:[1,2,3] }));

          }

          protected function _handler(e:AppEvent):void

          {

               // trace what is appended to the params object ("change" from ClassB)

               trace("ClassA AppEvent: " + e.params.change);

          }

     }

}

ClassB.as:

package

{

     import flash.display.Sprite;

     import flash.events.Event;

     import AppEvent;

     // using Sprite here to dispatch events (otherwise would

     // need to implement IEventDispatcher.. Sprite is easy

     public class ClassB extends Sprite

     {

          public function ClassB()

          {

               // how you'd listen for events sent to this class:

               // disabled to prevent infinite loops for this example

               // addEventListener(AppEvent.APP_EVENT, _handler);

               // wait to be added, then dispatch an event

               addEventListener(Event.ADDED_TO_STAGE, _init);

          }

          protected function _init(e:Event):void

          {

               removeEventListener(Event.ADDED_TO_STAGE, _init);

               // now dispatch a custom event, with data

               this.dispatchEvent(new AppEvent(AppEvent.APP_EVENT, { change:"This is from ClassB!" }));

               // you can name the data whatever you want, I used 'change' for

               // no special reason

          }

          protected function _handler(e:AppEvent):void

          {

               // trace what is appended to the params object ("change")

               trace("ClassB AppEvent: " + e.params.change);

          }

     }

}

Forgive any syntax errors, I typed completely from memory but I think you get the general idea. It's very easy to use events with custom data.

If you made those 3 files, opened a new AS3 document you'd just set it off via:

import flash.events.Event;

import ClassA;

addEventListener(Event.ENTER_FRAME, init);

function init(e:Event):void

{

     removeEventListener(Event.ENTER_FRAME, init);

     var cA:ClassA = new ClassA();

     addChild(cA);

}

goldfeverAuthor
Participant
December 7, 2012

Thank you for your reply but that is of no help at all, I know how to use custom events I do it all the time. The problem is that when I pass one through the parent application to another module somehting weird happens with the class type - please see the original question.

Thanks

sinious
Legend
December 7, 2012

Perhaps upgrade your event extender to support all the trimmings such as the example I posted. It's a shot in the dark but you didn't supply much code except an imcomplete event extender class.

Perhaps using a period in your type string is causing havoc and you didn't implement this as a type in your class: "parentApplication.thumbsDeleted".

When I send events from ClassA to ClassB and even send that back to ClassA there's no issue with type, it's always AppEvent. I tested one of my applications which daisy chains an even through 7 classes, re-dispatching them back up 4 levels. At each step AppEvent was the type.

I don't understand what you mean by this in either direction:

if I just use Event as the type passed in to the listener function like this:

    public function onThumbsDelete(evt:ThumbDeleteEvent):void{

...

evt is set as type ThumbDeleteEvent, did you mean evt:Event? Or are you saying you're trying to dispatch an event of type flash.events.Event to that handler? The former makes sense although you couldn't specify files but the latter makes no sense as it'd never type check as ThumbDeleteEvent so obviously the 'else' would always fire off.