views:

353

answers:

6

I have a parameter that needs to be passed along with an event. After unsuccessful attempts to place it on the type by extending the class, I've been advised in another SO question to write a custom event.

I tried this before but I couldn't figure out how to send it, because I just want to send another parameter with a normal Event.COMPLETE event on a FileReference. I can't have Event.COMPLETE fire and then dispatch my event because then I'll be in the same boat ... the needed parameter won't be in the initial Event.COMPLETE object so I won't be able to dispatch a new event passing that parameter on to the code that actually performs the work.

All help on this is greatly appreciated, need it badly. Thanks.

Basically, I need to replace the Event.COMPLETE functionality exactly as it is, I just need an event that will hold my extra property. Please tell me there's some way to do this.

A: 

Could you post some code so we can see how you are approaching this?

However I would highly recommend reading the flex live docs on creating and using custom events.

Here is a simple custom event based application, Take a look at the source, it might be what you are looking for.

jayWellings
+2  A: 

I'm not an expert, but the following is working for me. (Names changed to protect the innocent).

Here is one of my custom events:

import flash.events.Event;
public class SomethingHappenedEvent extends Event {
    public static const SOMETHING_COMPLETE:String = "PictureTakenComplete";
    public var passedValue:int;

    public function SomethingHappenedEvent(i:int) {
        passedValue = i;
        super(SOMETHING_COMPLETE);   
    }
}

I have a listener set up to listen for my custom event. When the custom event fires, my doSomething() function is executed. Here's how I set that up:

mySecret.addEventListener(SomethingHappenedEvent.SOMETHING_COMPLETE,doSomething);

Inside the doSomething() function I have access to event's passedValue parameter:

private function doSomething(e:SomethingHappenedEvent):void {
    trace("did something: " + e.passedValue);
}

Finally, here is how I dispatch a custom event elsewhere in the code, passing in a parameter:

this.dispatchEvent(new SomethingHappenedEvent(myCounter));
dustmachine
If you extend Event, make sure you override the clone method. Otherwise you'll get the problem from this question: http://stackoverflow.com/questions/527438/re-dispatching-event-in-flex/527461#527461
Richard Szalay
Right, but I imagine that you `dispatchEvent` at the end of your picture-taking function, or something. I need to have Event.COMPLETE from a FileReference, and I need my thing to execute at that time. I can't call `dispatchEvent` from `doSomething()` on a plain `Event.COMPLETE` because I don't have the property that I need to pass to the constructor within that function.Basically, I need to replace the `Event.COMPLETE` functionality exactly as it is, I just need an event that will hold my extra property. Please tell me there's some way to do this.
cookiecaper
so, your operations are: 1. load FileReference 2. on completion create an object with some value. Where does the value come from? Can I just set a variable before the FileReference and pass it into the function, will that do it for you? I'll bet I can whip that up.
dustmachine
+7  A: 

first you need to add an event listener to the Event.COMPLETE as normal since it is going to be dispatched automatically and theres nothing you can do about it. Inside that event handler you can then dispatch your own custom even that the rest of the application listens for with your custom property attached to it. heres a quick example:

your event handling code would look like:

yourObject.addEventListener(Event.COMPLETE, function(event:Event):void{

  var myEvt:MyEvent = new MyEvent(MyEvent.COMPLETE, myCustomProperty);
  dispatchEvent( myEvt );

})

and the MyEvent class looks like:

package
{

  import flash.events.Event;

  public class MyEvent extends Event
  {

    public static const COMPLETE:String = "MyEventComplete";

    var myCustomProperty:*;

    public function MyCustomEvent(type:String, prop:*) :void
    {

      myCustomProperty = prop;

      super(type);
      // if you want your event to bubble 
      // be sure to specify : super(type, true)
    }

   //override clone() so your event bubbles correctly
   public override function clone() :MyEvent {

     return new MyEvent(this.type, this.myCustomProperty)

   }
  }
}

you can now add event listeners for your custom event just like any other event:

addEventListener(MyCustomEvent.COMPLETE, someFunction);
greg
Hmm, so this means it's not possible to do what I want, basically. I'll have to come up with some hack. Thanks.
cookiecaper
Well its not really a hack. This is the proper way to create a custom event. A hack would be forcing `Event` to do something it wan't designed to do.
greg
Also, extending FileReference with a custom class (which listened for Event.COMPLETE and dispatched MyCustomEvent.COMPLETE) would make this approach reusable.
Michael Brewer-Davis
A: 
  1. Create Custom Event with data parameter
  2. Your class ( (for example MyObject) should catch Event.COMPLETE using addEventListener and dispatch your custom event MyCustomEvent with your data in it
  3. Catch your MyCustomEvent somewhere else (for example in MyAnotherObject)

MyCustomEvent.as

package
{
 import flash.events.Event;

 public class MyCustomEvent extends Event
 {
  public static const MY_CUSTOM_EVENT_COMPLETE:String = "myCustomEventComplete";

  public var data:Object;

  // Constructor
  public function CaretEvent(type:String, data:Object, bubbles:Boolean=false, cancelable:Boolean=false)
  {
   super(type, true, cancelable);

   this.data = data;
  }

  // Public Methods
  public override function clone():MyCustomEvent
  {
   return new MyCustomEvent(type, data, bubbles, cancelable);
  }
 }
}

MyObject.as

package
{
 import flash.events.EventDispatcher;
 import flash.events.Event;

 public class MyObject extends EventDispatcher
 {
  // Contructor
  public function MyObject()
  {
   addEventListener(Event.COMPLETE, onComplete)
  }

  // Private Methods
  private function onComplete(event:Event):void
  {
   dispatchEvent(new MyCustomEvent(MyCustomEvent.MY_CUSTOM_EVENT_COMPLETE, "This is my custom data"));
  }
 }
}

MyAnotherObject.as

package
{
 import flash.events.Event;
 import flash.events.EventDispatcher;

 public class MyAnotherObject extends EventDispatcher
 {
  // Constructor
  public function MyAnotherObject()
  {
   addEventListener(MyCustomEvent.MY_CUSTOM_EVENT_COMPLETE, onMyCustomEventComplete)
  }

  // Private Methods
  private function onMyCustomEventComplete(event:MyCustomEvent):void
  {
   trace(event.data);
  }
 }
}
zdmytriv
A: 

I usually do something like this, maybe not the best approach, but you should know this way is available...

myObj.addEventListener("creationComplete", function(e:Event):void{otherFunction(e, "another Arg")});
Chris Klepeis
A: 

From the sound of things, you may not need to extend FileReference, Event.COMPLETE, etc. if all you need is another property... will the following work for your purposes? If not, show me some code so we can be on the same page.

public function go():void {
    var downloadURL:URLRequest = new URLRequest("http://example.com/big.jpg");
    var otherParam:String = "another param";
    var fileRef:FileReference = new FileReference();
    fileRef.addEventListener(Event.COMPLETE, function(e:Event):void {
                                                handleLoad(e,otherParam); });
    fileRef.download(downloadURL);
}

public function handleLoad(e:Event,whatelse:String):void {
    Alert.show("we just loaded " + e.target + " with param " + whatelse);
}

That will get an extra parameter (whatelse) into the handleLoad() function that does the work. Or are you saying that at the time of the download you don't have the additional parameter?

dustmachine