I've injected some silly binding error in a large legacy project and am having trouble finding it.
This is the error output to the console:
warning: unable to bind to property 'length' on class 'String' (class
is not an IEventDispatcher)
I've tried stepping through with the debugger try to track down where this is happening but there are many thousands of lines of code and with event messaging, a very non-linear program execution.
Question: Is there any way to make Flash Builder break on a warning like this? If not, is there some other method, trick or hack for tracking this down?
This is caused by (wait for it...) trying to bind to a property that isn't marked as [Bindable]. In this case, you have a string variable whose length property is being used for data binding.
This is most likely caused by adding "myvar.length" as a property in the MXML tag for a component -- something like
<s:TextInput maxChars="{myInputString.length}" ...>
Flex will create the data binding for you automatically, but it doesn't realize at runtime that the property isn't Bindable - meaning, if there are changes to the property value the notification won't propagate to update the listeners.
Data binding uses mx.binding.PropertyWatcher to do the binding, and PropertyWatcher.updateParent is where the warning is output.
I have AdvancedDataGrid and I wanted to access dataProvider.getItemAt(i) in function in my view.
I'm not getting any errors nor warning and the code is compiling, but when I run this function I get this error:
Property getItemAt not found on mx.collections.HierarchicalCollectionView and there is no default value.
Why can't I do this? I saw some samples ane people was using this function.
This is how I call it:
var x:Object = _dg.dataProvider.getItemAt(i);
The AdvancedDataGrid's dataProvider is a generic object. That, basically, means the compiler will let any property/method access on it slide without issues.
The HierarchicalCollectionView does not have a getItemAt() method, which is why you get the runtime error. The Hierarchical collection, by nature, contains nested elements I'm not sure how you'd access a single element using a single index.
You probably want to use some form of getChildren() or getParentItem() method to get access to an individual node.
The places where you saw getItemAt() work were most likely using an ArrayCollection.
I have components in mxml and simply I want to listen these component's events from custom class methods.
I tried these;
list.addEventListener(NativeDragEvent.NATIVE_DRAG_START, new CustomDragClass().DragStart);
error: incorrect number of arguments, Expected 1.
In this question, Amargosh says to use _customDragClass.DragStart but didn't worked, too. Same error
How can I assign class method as event listener method ?
Edit: This is a working programming. I fixed the issue by clean build project on freakin FlashBuilder IDE.
I'm having difficulty with the last piece in the puzzle on AS3 events.
I understand target classes inherit from EventDispatch or implement IEventDispatch and can register (amongst other methods) event listeners.
However what do the target classes register with? If an Event happens, how does AS3 know to pass the Event to the target classes?
Regards,
shwell.
Read this article about event phases and it will make more sense:
http://livedocs.adobe.com/flex/3/html/help.html?content=events_02.html
Hope this helps. Have a great day.
You can look at how starling event works
starling even dispatcher
When a displayObject bubbles an event, it will check if the parent of the displayObject exist and add the parent to bubbleList if exist util the ancestor of displayObject is null.
The following code is in starling eventDispatcher
var element:DisplayObject = this as DisplayObject;
var chain:Vector.<EventDispatcher> = new <EventDispatcher>[element];
while ((element = element.parent) != null)
chain[int(length++)] = element;
In AS3, EventDispatcher is an implementation of the observer design pattern. This class implement the addEventLister, removeEventListener, dispatchEvent' andhasEventListener` methods. Internally, it also maintains a dictionary or similar data structure that contains the events which are currently being listened for, and a list of methods which have to be called when the event is dispatched. Something like this -
{"event1": [method7, method5, method3], "event2": [method3, method2], "event3": [method1]};
When addEventListener is called on an object, it creates a new key for the event in question and adds the method reference to its associated value list.
When dispatchEvent is called on the class, it fetches all the methods associated with the event and calls the methods attached with it. Each method is called with an instance of the Event class or its subclasses.
Removing an event listener obviously does the opposite of what adding does.
I guess you're missing of addEventListener() mechanics. This thing has a global side effect on event engine, registering a callback function along with caller this value to provide correct context of a fired event, with possible update of event.localX and event.localY properties by calling globalToLocal() either statically or dynamically, as the event bubbles up and down.
If you are, like me, confused about how does Flash player determine the target of an event - there is an internal "focus" pointer that determines which component of the SWF has keyboard focus, and that one is used to target keyboard events. For mouse events, most likely Flash engine calls getObjectsUnderPoint() to query for topmost IEventDispatcher compatible objects (not all of the DisplayObjects can process events), and that one is sent a mouse event, with the previous event's target to receive a say MouseEvent.ROLL_OUT or MouseEvent.MOUSE_OUT if the target has been changed. For other events, most likely the entire display list can react.
For objects in the display list, the following excerpt from Adobe is the answer "When Adobe® Flash® Player dispatches an Event object, that Event object makes a roundtrip journey from the root of the display list to the target node, checking each node for registered listeners.".
For non display objects, AS3 run time maintains a dictionary of all AS3 events containing bound variables. The bound variables are a reference to the event listeners.
I have a custom component called shopView which is an MXML skinnable component. I have a controller class called ShopController which takes care of showing this component in popup, updating info shown in the component etc.
Now, I wanted to maniupate some of the subcomponents of this ShopView after it has been created from the controller after the ShopView is created (creationComplete() event)
So, I have attached an event listener which intern does some initialization process
creationComplete="init(event)"
the init() function
private function init(event:FlexEvent):void{
event.stopImmediatePropagation();
initMenus();
initSlots();
dispatchEvent(event);
}
Attached another creation complete event from the controller class
_shop.addEventListener(FlexEvent.CREATION_COMPLETE,onShopCreated);
*_shop is the instance of ShopView*
Now, if you see the init() function, there I am stopping the event propagation, doing some initialization process and after that I am dispatching the event (for the shop controller do the rest of the job)
Now, this is crashing the app because the crationComplete event of the ShopView is recursively called. I was thinking the dispatchEvent will propagate to the other listerners but seems like it is propagating back to the same component.
I have fixed it by removing the e.stopImmediatePropagation() and dispatchEvent(event) lines from the init() function. But I want to know why it is happening like this?
Is it a known issue for the mxml/flex components? OR it is expected behavior?
Update: I am not doing same in .as as I said below. Got answer, basically its my stupidity :)
because I have not seen this behavior when I write .as classes where I
stopevent propagation and dispatch the event based on business logic.
Thanks in advance.
This is expected behavior.
When you redispatch an existing event dispatchEvent automatically clones it (since you can't dispatch the same event twice.) This clears any propagation-related flags.
May I ask why you want to redispatch CREATION_COMPLETE in this situation anyway? Both handlers will function just fine without the two lines you removed.