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;
Related
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
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.
For my custom components, when they go from enabled to disabled or disabled to enabled, I want to trigger a custom event.
I can't find any related events in the livedocs.
Any clues please?
UIComponent does dispatch an event of type enabledChanged from its set enabled method. Here is the source of that method:
public function set enabled(value:Boolean):void
{
_enabled = value;
// Need to flush the cached TextFormat
// so it recalcs with the disabled color,
cachedTextFormat = null;
invalidateDisplayList();
dispatchEvent(new Event("enabledChanged"));
}
You can listen to it using:
myComponent.addEventListener("enabledChanged", handleEnabledChanged);
If they're custom components, and I'm assuming you're extending UIComponent (or a child class), why don't you just override the Enabled setter method, then dispatch a custom event within that?
Something like:
override public function set enabled(value:Boolean):void {
super.enabled = value;
dispatchEvent(new EnabledChangedEvent());
}
I am rather new to flex and am trying to figure out how to listen for a custom event I have created. Let me give you a little background on my app first.
My directory structure is as follows.
assets
components
control
events
model
util
In the model class (which is bindable) I have an ArrayCollection which will get loaded with data via a web service call and a datagrid in a specific component will bind to that ArrayCollection and display the data. The web service is invoked via a button press which initiates the search through an event.
model/ApplicationModel.as
[Bindable]
public class ApplicationModel
{
//put specific model components here
public var data:ArrayCollection;
//the one instance in this Singleton
private static var _instance:ApplicationModel;
public function ApplicationModel()
{
if (_instance != null) throw new Error("ApplicationModel already exists!");
}
public static function getInstance():ApplicationModel
{
if (_instance == null) _instance = new ApplicationModel();
return _instance;
}
}
components/SearchBox.mxml
<mx:HBox xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script>
<![CDATA[
import com.homedepot.di.tp.SCVTools.events.*;
private function doSearch():void
{
var query:String = searchTI.text;
//only want to dispatch an event if there is something to query
if (query) dispatchEvent(new CustomEvent(CustomEvent.UPDATE_START,query));
}
]]>
</mx:Script>
<mx:Label text="Enter Search Term"/>
<mx:TextInput id="searchTI" enter="doSearch()" />
<mx:Button label="Search" click="doSearch()"/>
</mx:HBox>
This search functionality works fine and will return the data that I want. What I need to be able to know is when this web service call is done so the view component can update other aspects of the view accordingly (hide columns of datagrid based on the data returned as an example).
My Application.mxml file will wire up my controller to listen for the CustomEvent. The controller will then delegate the work to actually call the web service and get the data. The delegate will create an HTTPService object and get the data. It will also process results of the HTTPService. I am currently trying to dispatch a new event in the function that handles the result of the HTTPService call. This does not seem to be working and it makes sense since the event will never bubble to my view component.
snippet of control/DataUpdateDelegate.as
public override function parse(event:ResultEvent):void
{
super.parse(event);
try
{
Application.debug("DataUpdateDelegate:parse");
var data:Object = event.result.records.record;
model.data = data as ArrayCollection;
dispatchEvent(new CustomEvent(CustomEevent.UPDATE_END) );
}
catch (error:Error)
{
handleError(error);
}
}
I have tried to wire this UPDATE_END event up in the Application.mxml file but that does not seem to work either.
Does anyone have any suggestions on how my view to listen to this event that is not dispatched from a child component but rather from an ActionScript class that knows nothing about the view component?
Thanks,
Thomas
You could bind a specific function to the data property using BindingUtils when your ApplicationModel is first set in your view:
public function set model(applicationModelInstance:ApplicationModel):void
{
_applcationModelInstance = applicationModelInstance;
BindingUtils.bindSetter(dataRefreshed, _applicationModelInstance, "data");
}
protected function dataRefreshed(value:Object):void
{
// do whatever you need to do here.
// value==applicationModelInstance.data
}
De-registering a binding like this to avoid memory leaks is a bit tricky, but since your ApplicationModel is a singleton you don't need to anyways.
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