views:

758

answers:

1

Suppose you have a MyView.mxml file, which is basically a Panel with several children (Form, FormItems, Buttons...).

Is it possible to iterate over the MyView and get all the information about its children (types, id ...) before it is displayed.

In my Main.mxml if I have this function

    public function iterateOverChildren(comp:Container):void {
        // Get the number of descriptors.
        trace("Running iterateOverChildren for " + comp.id);
        if (comp != null)
        {
        var n:int = comp.childDescriptors.length;
        for (var i:int = 0; i < n; i++) {
            var c:ComponentDescriptor = comp.childDescriptors[i];
            var d:Object = c.properties;

            // Log ids and types of objects in the Array.
            trace(c.id + " is of type " + c.type);

            // Log the properties added in the MXML tag of the object.
            for (var p:String in d) {
                trace("Property: " + p + " : " + d[p]);
            }
        }
        }
    }

Why does this call not work ?

var myV = MyView(); iterateOverChildren(myV);

It only works if I add a statement like addChild(myV); before the iterateOverChildren call. (But that's not what I want, I want to iterate the descriptions without adding it to display).

When I read this http://livedocs.adobe.com/flex/3/html/help.html?content=layoutperformance%5F06.html

I thought the "childDescriptors" method is independent from the life cycle, it would let me introspect the component without adding to display. What did I miss ? How do I introspect a component before displayed.

+2  A: 

There are multiple ways of component instantiation in Flex.

If you use the constructor in ActionScript, you get a bare metal object where nothing but construction of the object itself has been completed. In particular, this new object has not yet instantiated its child views, that's why you don't see anything when you look at the results of getChildren().

If you write down your component in MXML, the MXML compiler creates ComponentDescriptors instead of "real" objects. These hold all information you specified for the object in MXML (properties, bindings, event handlers etc), and the runtime uses them to create real objects at the appropriate time. "Appropriate time" usually means "when the object is added to the display list". That's why you only see children after calling addChild() (technically, not immediately after calling addChild(), but only after your newly instantiated object has dispatched its creationComplete event).

Simon
Thanks Simon. I think I still not understand 100%, the usage of childDescriptors over getChildren(). "All containers have a childDescriptors property.Depending on the value of the creationPolicy property, Flex immediately begins instantiating controls inside the containers or it defers their instantiation. If instantiation is deferred, you can use the properties of this Array to access the ComponentDescriptor of each component and create that object at a specified time."Is your interpretation of the above that the descriptors are not immediately available.
Alex E. Oscar
The descriptors are immediately available, however only for objects created in MXML code. If you instantiate an object in ActionScript by calling the constructor as in `var myV = MyView();`, you're getting a real object which does not have childDescriptors.
Simon
Got it thanks.If I do thisvar myV = MyView(); myV.initialize();iterateOverChildren(myV);I will get the information. How can I make this recursive ? In my iterateIVerChildren code var c is a ComponentDescriptor. Can I find c's children ?
Alex E. Oscar
UIComponent.initialize() already works recursively. After calling it, you should be able to access myV's children via getChildren().
Simon
Also, reading the Flex source has helped me in the past when the documentation was unclear. It's pretty readable.
Simon
Unfortunately, I am back to square one. Running initialize() explicitly caused Runtime Errors on some of my components. I appreciate if someone can take a stab for writing the code for function displayAllTheIdsRecursively() below. (I am not lazy, I am just stuck).var myV:MyView = new MyView();// Below function would display the id of all UIComponents (recursive) from MyView displayAllTheIdsRecursively(myV);
Alex E. Oscar
You will probably need to wait until the initialize is finished. So set an event handler for the initialized event (I think that's the right one) then you should be able to get to the childDescriptors.
James Ward