move data from progress event to another class - apache-flex

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

Related

Listen to custom event in flex

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;

Itemrenderer Dispatch Custom Event

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

How do I addEventListener to custom actionscript class?

I have an actionscript class MyClass that extens NavigatorContent. I instantiate the class as a custom MXML NavigatorContnent component for an Accordion component. MyClass has a Button component that I have tried to attach an event listener to. I want the event to bubble so that I can have the handler in the Accordion component.
MyClass
package comp
{
import flash.events.Event;
import flash.events.MouseEvent;
[Event(name="selectEvent", type="flash.events.Event")]
public class MyClass extends NavigatorContent
{
public function MyClass()
{
super();
btnSelect.addEventListener(MouseEvent.CLICK, selectClickDispatcher);
}
public function selectClickDispatcher(event:MouseEvent):void
{
event.currentTarget.dispatchEvent(new Event("selectEvent",true));
}
}
}
From here I have the instantiated component nested in the Accordion. I am pretty sure the problem is in this class definition because when I set a breakpoint at the selectClickHandler, the code does not break. In case I am wrong I will post the rest of the components.
Custom component named MySubComp.mxml
<comp:MyClass
...I have a few more spark components here and nothing else...
/>
Accordion
<mx:Accordion>
<fx:Script> //omitted CDATA tags to save space
protected function selectEventHandler(event:Event):void
{
Alert.show("Value Selected");
}
</fx:Script>
//custom components are in the navs package
<navs:MySubComp selectEvent = "selectEventHandler(event)"/>
</mx:Accordion>
You have added the metadata to the class definition
[Event(name="selectEvent", type="flash.events.Event")]
so all you need to do in mxml is
<comp:MyClass selectEvent="event_handler(event)"
..... />
In AS3, you add an event listener by
myClass.addEventListener("selectEvent", event_handler);
P.S. Your class will have to extend EventDispatcher
Your class either needs to extend a DisplayObject class, or directly inherit from EventDispatcher in order to be able to use events. Forget about implementing IEventDispatcher as there's a special piece of black code somewhere that means that EventDispatcher is the only class that can set the target property of the Event class (I've tried it before).
Consider using other alternatives. Events in Flash tend to be slow and create objects all the time. Callbacks are a good system if you need something simple.
public class A
{
public var onSomething:Function = null;
public function foo():void
{
if( this.onSomething != null )
this.onSomething();
}
}
public class B
{
public function B()
{
var a:A = new A;
a.onSomething = this._somethingCalled; // set the callback
a.init();
}
private function _somethingCalled():void
{
trace( "hello there" );
}
}
You can also take a look at the Signals project: https://github.com/robertpenner/as3-signals/wiki
Signals are vastly superior to normal Flash events, and there's no restriction on the type of object that can use them (i.e. non-DisplayObject objects can still add event listeners and dispatch events). It's also faster and has a smaller memory footprint.
In case someone needs the real Actionscript-3 event dispatching to be used >>> this <<< is very helpful. I don't know if it is really slow but it meets the AS-3 standards.

Not receiving an event fired from an .AS 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.

Flex event will only fire once

In an AIR application, I have a private variable and a setter:
private var _saveResult
public function set saveResult( result:String ):void
{
_saveResult = result;
dispatchEvent( new resultUpdatedEvent( _saveResult ));
}
The first time that I set "saveResult" the event fires. But it will never fire again unless I restart the application.
If I change the setter to:
public function set saveResult( result:String ):void
{
_saveResult = result;
if ( result != null)
{
dispatchEvent( new resultUpdatedEvent( _saveResult ));
}
}
The problem goes away, I can set the variable many times and the event fires every time.
My question:
Am I doing something wrong here? If not, can anyone explain to me whats happening? If so, what SHOULD I be doing?
Thanks!
It looks like you're constructing your event incorrectly. The first parameter of an Event object should always be a string. So in this case you'd want to always use the same string so you could listen for the event. What does your resultUpdatedEvent class look like? You'll want it to look something like this:
package myEvents
{
import flash.events.Event;
public class PropertyChangeEvent extends Event
{
public static const PROPERTY_CHANGE:String = "propertyChange";
public var result:String = "";
// Public constructor.
public function PropertyChangeEvent (type:String,
result:String="") {
// Call the constructor of the superclass.
super(type);
// Set the new property.
this.result= result;
}
// Override the inherited clone() method.
override public function clone():Event {
return new PropertyChangeEvent(type, result);
}
}
}
That way, when you go to dispatch your event, you can construct the event as follows:
new PropertyChangeEvent(PropertyChangeEvent.PROPERTY_CHANGE, result);
That way, you're listening for the event "PropertyChangeEvent.PROPERTY_CHANGE", which never changes. The problem is now your event listener is probably listening for an event represented by the string saved in result, and obviously, this changes after the first time it's set, so there's no way to assign a listener to it.
For more information about how events work in AS3: http://livedocs.adobe.com/flex/3/html/help.html?content=events_02.html
Per the comments...
There was no event dispatcher problem.
I misdiagnosed the problem, the REAL problem was that if you have a [Bindable] property and you use a setter, and you set it for the current value, flex will ignore it. SO, you have several choices:
1) give the getter and setter different names. Seems like a "bad idea" but it does fix the problem.
2) remove [Bindable] from either the class (my problem) or the property. If the class does not implement IEventDispatcher, you will need to do so. You can simply "extends Sprite" to see it work, but that seems like a "bad idea" as a solution, so I implemented IEventDispatcher per the example at the end of this page: http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/flash/events/IEventDispatcher.html
3) I am sure that there is a way to get around this bug, but I don't actually NEED the class to be [Bindable] so I did not find a work around.

Resources