I'm trying to dispatch a custom event from a custom ItemRenderer
This is my custom event
package events
{
import customClass.Product;
import flash.events.Event;
public class CopyProductEvent extends Event
{
public static const COPY_PRODUCT:String = "COPY_PRODUCT";
public var picked:Prodotti;
public function CopyProductEvent(type:String, picked:Product)
{
super(type);
this.picked = picked;
}
}
}
In the itemRenderer I have a function that does that:
private function sendEvent(o:Product):void
{
dispatchEvent(new CopyProductEvent(CopyProductEvent.COPY_PRODUCT,o));
}
And in the main application I have a spark List and I tried to add an EventListener both to the application and the list itself, but they never be called...
this.addEventListener(CopyProductEvent.COPY_PRODUCT,
function(e:Product):void{
...
});
list.addEventListener(CopyProductEvent.COPY_PRODUCT,
function(e:Product):void{
...
});
Why?!? Where am I doing wrong?
The event from the function is dispatched correctly... I can't intercept it..
Sounds like your event isn't bubbling.
Add the bubbles argument (which by default, is false) in your Custom event constructor:
public function CopyProductEvent(type:String, picked:Product, bubbles:Boolean = true)
{
super(type,bubbles);
this.picked = picked;
}
A nice explanation on Event bubbling in AS3 can be found here:
Event Bubbling in AS3
Related
I created a custom event with a custom property in actionscript. I can dispatch a custom event (in Main.mxml) with a custom property but I'm not able to listen for this event anywhere else in my application. I'm trying to listen to this event in a custom component.
When I debug I can confirm that the event gets dispatched correctly with the right value.
Snippet of Main.mxml:
var userid:String = result.charAt(4);
//dispatch a custom event in which we store the userid
var event_userid:MyEvent = new MyEvent(MyEvent.COMPLETE,userid);
dispatchEvent(event_userid);
CustomEvent class:
package ownASClass
{
{
//http://stackoverflow.com/questions/1729470/attaching-a-property-to-an-event-in-flex-as3
import flash.events.Event;
public class MyEvent extends Event
{
public static const COMPLETE:String = "MyEventComplete";
public var myCustomProperty:*;
public function MyEvent(type:String, prop:*) :void
{
super(type,true);
myCustomProperty = prop;
}
//override clone() so your event bubbles correctly
override public function clone() :Event {
return new MyEvent(this.type, this.myCustomProperty)
}
}
}
}
I listen to this event in my custom component:
//init gets called as: initialize="init();
protected function init():void
{
//add evt listener for custom event to get userid
this.parentApplication.addEventListener(MyEvent.COMPLETE,getUserid);
//my custom component is part of a viewstack defined in main.mxml
}
protected function getUserid(event:Event):void
{
//do something (but this never gets called)
}
protected function init():void
{
//add evt listener for custom event to get userid
this.parentApplication.addEventListener(MyEvent.COMPLETE,getUserid);
//my custom component is part of a viewstack defined in main.mxml
}
Please try to change above line as follows -
this.addEventListener(MyEvent.COMPLETE,getUserid);
Events typically 'bubble up' the chain from child windows to parent to application(main.mxml).
http://livedocs.adobe.com/flex/3/html/help.html?content=events_08.html
If you are trying to use an event to signal some sub-object you'll need to target it there and have a registered event listener.
Used a workaround for this, realized I didn't really need to dispatch a custom event.
Declared my userid in main application and called it in my component with:
public var userid:String = FlexGlobals.topLevelApplication.userid;
Ok this probably sounds dumb but Im a complete beginner in Flex programming.
I have an application with a main .mxml file, and a certain class Foo that I call from the .mxml
In Foo, I make a URLRequest and listen for the Complete event. Then I found myself with the returned data in a Foo function, but I have no idea how to communicate it to the .mxml part of the applicaton ! I looked into ArrayCollections but I can't seem to understand how they work and whether it might help. Isn't there a way to modify, from inside the class, a variable with a global scope ?
This sounds like a small application, but if it's a large application you might want to look at a micro-framework like RobotLegs
If you have your Foo class extend EventDispatcher then it will be able to send events and have the main MXML app listen for said events.
package com.example
{
import flash.events.EventDispatcher;
import com.example.events.MyEvent;
public class Foo extends EventDispatcher
{
public function doAction():void
{
var someData:String = "blah";
dispatchEvent(new MyEvent(MyEvent.SOMETHING_HAPPENED, someData));
}
}
}
A Custom event with a payload (in this case a string)
package com.example.events
{
import flash.events.Event;
public class MyEvent extends Event
{
static public const SOMETHING_HAPPENED:String = "somethingHappened";
private var _myData:String;
public function get myData():String
{
return _myData;
}
public function MyEvent(type:String, myData:String, bubbles:Boolean=false, cancelable:Boolean=false)
{
_myData = myData;
super(type, bubbles, cancelable);
}
override public function clone():Event
{
return new MyEvent(type, myData, bubbles, cancelable);
}
}
}
Working with your Foo class from the main file:
public function EventDispatcherExample() {
var foo:Foo = new Foo();
foo.addEventListener(MyEvent.SOMETHING_HAPPENED, actionHandler);
foo.doAction();
}
private function actionHandler(e:MyEvent):void {
trace("my data is: " + e.myData);
}
import mx.core.FlexGlobals;
FlexGlobals.toplevelApplication.varName;
Your Foo class can dispatch an event and have something in you main.mxml listen for that event. I am sure that I could create an example. I think it is under customer events in Flex documentation. This is assuming I understand the question.
As John said, an event is your best choice.
If you'd like some example code, I provided some for a similar question here: Data from Popup to Main Application?
An event might be the best way to do it as it has been stated.
Another approach is to dispatch an event like this
dispatchEvent(new Event('somethingHappened'));
and also create a get method in your class for the data you need to get.
Then all you have to do in your main app is this
var foo:Foo = new Foo();
foo.addEventListener('somethingHappened', actionHandler);
private function actionHandler(e:Event):void
{
trace(foo.memberData);
}
This way might be more suitable if the data should be a class member anyway and if you would like to avoid creating a new event class.
I have 2 files, 1 to dispatch the event and 1 to receive it (of course in addition to the event class itself).
I've done this before with both dispatching and receiving files being mxml, but this time the dispatching file is an actionscript class, and it's not working this time. Is it different for actionscript classes?
Here's a dumbed down version
The dispatching class dispatches the event as soon as it's created.
public class ASClass extends UIComponent{
public function ASClass(){
dispatchEvent(new MyEvents(MyEvents.FIRE_EVENT));
}
}
in my main mxml app, I instantiate the ASClass which automatically dispatch the event as soon as it's created and the main mxml app should receive back. But something's not working.
protected function appCComplete(event:FlexEvent):void{
addEventListener(MyEvents.FIRE_EVENT, gotEvent);
var asClass:ASClass = new ASClass();
}
protected function gotEvent(event:MyEvents):void{
Alert.show("got event");
}
addEventListener(MyEvents.FIRE_EVENT, gotEvent);
is same as
this.addEventListener(MyEvents.FIRE_EVENT, gotEvent);
which listens for FIRE_EVENT dispatched by this object - your main mxml app. To listen for events fired from asClass object, you have to call addEventListener on that object.
asClass.addEventListener(MyEvents.FIRE_EVENT, gotEvent);
Thus, you cannot listen for events fired from the constructor. The following code shows the correct way to listen to the events fired by the asClass object (from anywhere but the constructor).
protected function appCComplete(event:FlexEvent):void{
var asClass:ASClass = new ASClass();
asClass.addEventListener(MyEvents.FIRE_EVENT, gotEvent);
}
protected function gotEvent(event:MyEvents):void{
Alert.show("got event");
}
If you think about it, you can see that it makes sense. The constructor is used to create an object - event subscribers are normally interested in some actions/changes occurring to the object once the object is fully built and functional.
That said, you can pass a reference to this or the function to the constructor of ASClass and then assign that function as the event listener from within the constructor if you want.
public class ASClass extends UIComponent{
public function ASClass(listener:Function){
this.addEventListener(MyEvents.FIRE_EVENT, listener);
dispatchEvent(new MyEvents(MyEvents.FIRE_EVENT));
}
}
var asClass:ASClass = new ASClass(this.gotEvent);//pass the function.
//or
public class ASClass extends UIComponent{
public function ASClass(listenerObj:Object){
this.addEventListener(MyEvents.FIRE_EVENT, listenerObj.gotEvent);
dispatchEvent(new MyEvents(MyEvents.FIRE_EVENT));
}
}
var asClass:ASClass = new ASClass(this);//pass the object.
Personally, I can't think of many scenarios where I'd want to go this way: consider some redesigning so that you listen to the events after the constructor returns.
package com.services
{
import com.asfusion.mate.events.ResponseEvent;
import com.events.navigation.DesgManagementEvent
import flash.events.EventDispatcher;
import mx.controls.Alert;
public class UserManager extends EventDispatcher
{
[Bindable]
public var addResult:String
[Bindable]
public var user:User
public function UserManager()
{
}
public function addUsersResult(Result:String):void {
addResult = Result
//Alert.show(event.result.toString());
Alert.show(addResult);
backHome();
}
private function addUsersFault(event:ResponseEvent):void {
Alert.show(event.faultString, "Error Executing Call");
}
private function backHome():void {
this.dispatchEvent(new DesgManagementEvent(DesgManagementEvent.DES_HOME));
}
}
}
I am able to get the result, but not able to dispatch the event from the custom actionScript class. I googled and got the riposte that you need to add it to display list.
Can anyone figure out where i am going wrong. The method backHome is not being called at all.
I believe you are expecting to get DesgManagementEvent in the event map and because you don't see it being handled, you believe that bakcHome is not being called.
As you said, events dispatched from an object component that is not in the display list will never reach the event map. You need to pass the dispatcher and use that to dispatch the event. You can pass it in the constructor (first objectBuilder) or as a property (second objectBuilder).
<EventHandlers type="{FlexEvent.INITIALIZE}">
<ObjectBuilder generator="{MyManager}" constructorArguments="{scope.dispatcher}"/>
<ObjectBuilder generator="{MyManager2}">
<Properties dispatcher="{scope.dispatcher}"/>
</ObjectBuilder>
</EventHandlers>
If you use the constructor, then it will look something like this:
public function MyManager(dispatcher:IEventDispatcher)
{
this.dispatcher = dispatcher;
}
Then you will use your dispatcher property to dispatch the event:
dispatcher.dispatchEvent(new DesgManagementEvent(DesgManagementEvent.DES_HOME));
Are you sure you're receiving type String when addUsersResult() is called?
in Flex if i have a loader class (i.e., XMLLoader) and a document class (document.as) and in document.as I'm instantiating XMLLoader
var ldr:XMLLoader = new XMLLoader(url);
... and on the document.as class I have a text box, which I would like updated with the progress from that XMLLoader is making by using URLLoaders progress event, continously. Meaning, the box would show the load in bytes that it is recieving
I'm not sure how to constantly push data out of an event and add it to another class. For example:
myLstnr.addEventListener(ProgressEvent.PROGRESS, getProgress);
private function getProgress():void
{
// as progress updates, move it to document.as class's textbox
{
You will want to re-dispatch the ProgressEvent. You can use a custom made event to store your event object. So for example:
private function getProgress(event:ProgressEvent):void {
dispatchEvent(new CustomObjectDataEvent(event, 'progress'));
}
Where CustomObjectDataEvent is a custom event class that you create that stores an object(the ProgressEvent) in your custom event object. Here is an example implementation of the custom event that stores this object:
package events
{
import flash.events.Event;
public class CustomObjectDataEvent extends Event
{
public var objectData:Object;
public function CustomObjectDataEvent(objectData:Object, type:String, bubbles:Boolean=false) {
super(type, bubbles);
this.objectData = objectData;
}
public override function clone():Event {
return new CustomObjectDataEvent(objectData, type, bubbles);
}
}
}
Check out: http://livedocs.adobe.com/flex/3/html/createevents_3.html for more information on dispatching custom events.
Your event handler (getProcess) must accept the ProgressEvent as a parameter. From that, you get the needed info. When you do, just write it out to the text field you want, e.g.
document.textfield.text = event.bytesLoaded;
You can dispatch an event to the other class from inside your getProgress(). Creating custom events