Flex 3 – Must I add components before setting their attributes when using AS3

apache-flexcomponentsflex3mxml

Let us say that I have a Flex 3 mxml component, call it A. A has a get/set attribute called 'b'. Within A I have another internal component C, which is specified using mxml. When "instantiating" component A within mxml, I can specify the value of b at declaration, and everything works fine. However, when I initialize the component using Actionscript, I must first add the component to a rendered container before I can set the attribute (in this case 'b') of said component. This happens when the setter for attribute 'b' somehow accesses C within A.

So, this fails at runtime (it says that C is null)…

var a:A = new A();
a.b = "woopy"; //Sets the Label (declared in mxml) withn A to "woopy"
this.addChild(a);

On the other hand, either of the following will work

<customNamespace:A b="woopy"/>

or

var a:A = new A();
this.addChild(a);
a.b = "woopy"; //Sets the Label (declared in mxml) withn A to "woopy"

As shown, no runtime error message is thrown when a attribute is set after a component is added to a container. Ok, this makes sense, I suppose the internals of the component are not actually created until the component is added to a container. Still, this is kind of annoying. Is there any way to guarantee that the component internals are fully rendered without adding it to a container? I don't like the way it feels different when I am using actionscript vs mxml. I want a solution so that basically declaring A in mxml with no attribute "arguments" is equivalent to declaring A using the new operator in AS. At least, in terms of the internal state of A.

Best Answer

To force a control to create its child controls you have to call the initialize method.

i.e. this should work :

var a:A = new A();
a.initialize();
a.b = "woopy";
this.addChild(a);

However, what I've been doing so far when declaring mxml controls is binding the internal controls to public variables declared in a script block. e.g.

<?xml version="1.0" encoding="utf-8"?>
<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml">
    <mx:Script>
        <![CDATA[
            [Bindable]
            public var labelText:String = "[Default]";
        ]]>
    </mx:Script>
    <mx:Label text="{labelText}"/>
</mx:Canvas>

This way you can set your parameters without having to worry about whether the controls have been created or not.

Related Topic