Adobe Flex 3 Help

Creating and managing component instances at run time

You typically use MXML to lay out the user interface of your application, and use ActionScript for event handling and run-time control of the application. You can also use ActionScript to create component instances at run time. For example, you could use MXML to define an empty Accordion container and use ActionScript to add panels to the container in response to user actions.

About the display list and container children

Flash Player maintains a tree of visible (or potentially visible) objects that make up your application. The root of the tree is the Application object, and child containers and components are branches and leaf nodes of the tree. That tree is known as the display list. When you add child components to a container or remove child components from a container, you are adding and removing them from the display list. You can also change their relative positions by changing their positions in the display list.

Although the display list is a tree rooted at the top of the application, when you manipulate a container's children in ActionScript by using the container's methods and properties, you only access the container's direct children, and you treat them as items in a list with an index that starts at 0 for the container's first child in the display list.

The Container class includes the numChildren property, which contains a count of the number of direct child components that the container has in the display list. The following HBox container, for example, includes two child components, so the value of its numChildren property is 2:

<mx:HBox id="myContainer">
    <mx:Button click="clickHandler();"/>
    <mx:TextInput/>
</mx:HBox>

You can access and modify a container's child components at run time by using the addChild(), addChildAt(), getChildren(), getChildAt(), getChildByName(), removeAllChildren(), removeChild(), and removeChildAt() methods of the Container class. For example, you can iterate over all of the child componens of a container, as the following example shows:

private function clickHandler():void {
    var numChildren:Number = myContainer.numChildren;
    for (var i:int = 0; i < numChildren; i++) {
        trace(myContainer.getChildAt(i));
    }
}

The Container class also defines the rawChildren property that contains the full display list of all of the children of a container. This list includes all the container's children, plus the DisplayObjects that implement the container's chrome (display elements), such as its border and the background image. For more information, see Accessing display-only children.

Obtaining the number of child components in a container or application

To get the number of direct child components in a container, get the value of the container's numChildren property. The following application gets the number of children in the application and a VBox container. The VBox control has five label controls, and therefore has five children. The Application container has the VBox and Button controls as its children, and therefore has two children.

<?xml version="1.0"?>
<!-- containers\intro\VBoxNumChildren.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
    <mx:Script>
      <![CDATA[
            // Import the Alert class.
            import mx.controls.Alert;
    
            public function calculateChildren():void {
                var myText:String = new String();
                myText="The VBox container has " + 
                    myVBox.numChildren + " children.";
                myText+="\nThe Application has " + 
                    numChildren + " children.";
                Alert.show(myText);
            }        
        ]]>
    </mx:Script>

    <mx:VBox id="myVBox" borderStyle="solid">
        <mx:Label text="This is label 1."/>
        <mx:Label text="This is label 2."/>
        <mx:Label text="This is label 3."/>
        <mx:Label text="This is label 4."/>
        <mx:Label text="This is label 5."/>
    </mx:VBox>  
    
    <mx:Button label="Show Children" click="calculateChildren();"/>
</mx:Application>

The executing SWF file for the previous example is shown below:

In the main MXML application file, the file that contains the <mx:Application> tag, the current scope is always the Application object. Therefore, the reference to the numChildren property without an object prefix refers to the numChildren property of the Application object. For more information on accessing the root application, see About scope.

Accessing display-only children

The numChildren property and getChildAt() method let you count and access only child components. Also, the container may contain style elements and skins, such as the border and background. The container's rawChildren property lets you access all children of a container, including the component "content children" and the skin and style "display children." The object returned by the rawChildren property implements the IChildList interface. You then use methods and properties of this interface, such as getChildAt(), to access and manipulate all the container's children.

Creating and removing components at run time

To create a component instance at run time, you define it, set any properties, and then add it as a child of a parent container by calling the addChild() method on the parent container. This method has the following signature:

addChild(child:DisplayObject):DisplayObject 

The child argument specifies the component to add to the container.

Note: Although the child argument of the method is specified as type DisplayObject, the argument must implement the IUIComponent interface to be added as a child of a container. All Flex components implement this interface.

For example, the following application creates an HBox container with a Button control called myButton:

<?xml version="1.0"?>
<!-- containers\intro\ContainerAddChild.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">

    <mx:Script>
        <![CDATA[
            import mx.controls.Button;

            public function addButton():void {
                var myButton:Button = new Button();
                myButton.label = "New Button";
                myHBox.addChild(myButton);
            }
        ]]>
    </mx:Script>

    <mx:HBox id="myHBox" initialize="addButton();"/>
</mx:Application>

The executing SWF file for the previous example is shown below:

This example creates the control when the application is loaded rather than in response to any user action. However, you could add a new button when the user presses an existing button, as the following example shows:

<?xml version="1.0"?>
<!-- containers\intro\ContainerAddChild2.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" 
    horizontalAlign="left">

    <mx:Script>
        <![CDATA[
            import mx.controls.Button;

            public function addButton():void {
                var myButton:Button = new Button();
                myButton.label = "New Button";
                myHBox.addChild(myButton);
            }
        ]]>
    </mx:Script>

    <mx:HBox id="myHBox">
        <mx:Button label="Add Button" click="addButton();"/>
    </mx:HBox>
</mx:Application>

The executing SWF file for the previous example is shown below:

The following image shows the resulting application after the user presses the original (leftmost) button three times:

Application after the user presses the original (leftmost) button three times

You use the removeChild() method to remove a control from a container. Flex sets the parent property of the removed child. If the child is no longer referenced anywhere else in your application after the call to the removeChild() method, it gets destroyed by a garbage collection process. The following example removes a button from the application when the user presses it:

<?xml version="1.0"?>
<!-- containers\intro\ContainerRemoveChild.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
    <mx:Script>
        <![CDATA[
            public function removeButton():void {
                myHBox.removeChild(myButton);
            }
            
            private function resetApp():void {
                if (myHBox.numChildren == 0) {
                    myHBox.addChild(myButton);              
                }
            }
        ]]>
    </mx:Script>

    <mx:HBox id="myHBox">
        <mx:Button id="myButton" 
            label="Remove Me" 
            click="removeButton();"
        />
    </mx:HBox>
    <mx:Button label="Reset" click="resetApp();"/>
</mx:Application>

The executing SWF file for the previous example is shown below:

For additional methods that you can use with container children, see the Container class in the Adobe Flex Language Reference.

Example: Creating and removing a child of a VBox container

The following example uses MXML to define a VBox container that contains two Button controls. You use one Button control to add a CheckBox control to the VBox container, and one Button control to delete it.

<?xml version="1.0"?>
<!-- containers\intro\ContainerComponentsExample.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">

    <mx:Script>
      <![CDATA[

        // Import the CheckBox class.
        import mx.controls.CheckBox;

        // Define a variable to hold the new CheckBox control.
        private var myCheckBox:CheckBox;
        
        // Define a variable to track if the CheckBox control 
        // is in the display list.
        private var checkBoxDisplayed:Boolean = false;
        
        public function addCB():void {
            // Make sure the check box isn't being displayed.
            if(checkBoxDisplayed==false){
                // Create the check box if it does not exist.
                if (!myCheckBox) {
                    myCheckBox = new CheckBox();
                }

                // Add the check box.
                myCheckBox.label = "New CheckBox";
                myVBox.addChild(myCheckBox);
                checkBoxDisplayed=true;
            }
        }
    
        public function delCB():void {
            // Make sure a CheckBox control exists.
            if(checkBoxDisplayed){
                myVBox.removeChild(myCheckBox);
                checkBoxDisplayed=false;
            }
        }        
      ]]>
    </mx:Script>

    <mx:VBox id="myVBox">
        <mx:Button label="Add CheckBox" 
            click="addCB();"/>          
        <mx:Button label="Remove CheckBox" 
            click="delCB();"/>
    </mx:VBox>
</mx:Application>

The executing SWF file for the previous example is shown below:

The following image shows the resulting application after the user presses the Add CheckBox button:

Application after the user presses the Add CheckBox button

Example: Creating and removing children of an Accordion container

The following example adds panels to and removes them from an Accordion container. The Accordion container initially contains one panel. Each time you select the Add HBox button, it adds a new HBox container to the Accordion container.

<?xml version="1.0"?>
<!-- containers\intro\ContainerComponentsExample2.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
    <mx:Script>
        <![CDATA[

            /* Import HBox class. */
            import mx.containers.HBox;
    
            /* Array of created containers. */
            private var hBoxes:Array = [];

            public function addHB():void {
                /* Create new HBox container. */
                var newHB:HBox = new HBox();
                newHB.label="Label: " + String(hBoxes.length);

                /* Add it to the Accordion container, and to the 
                   Array of HBox containers. */
                hBoxes.push(myAcc.addChild(newHB));
            }

            public function delHB():void {
                /* If there is at least one HBox container in the Array, 
                   remove it. */
                if (hBoxes.length>= 1) {
                    myAcc.removeChild(hBoxes.pop());
                }
            }
      ]]>
    </mx:Script>

    <mx:VBox>
        <mx:Accordion id="myAcc" height="150" width="150">
            <mx:HBox label="Initial HBox"/>
        </mx:Accordion>
        
        <mx:Button label="Add HBox" click="addHB();"/>
        <mx:Button label="Remove HBox" click="delHB();"/>       
    </mx:VBox>
</mx:Application>

The executing SWF file for the previous example is shown below:

Controlling child order

You can control the order of children by adding them in a specific order. You can also control them as follows:

  • By using the addChildAt() method to specify where among the component's children to add a child
  • By using the setChildIndex() method to specify the location of a specific child among a component's children in the display list

Note: As with the addChild() method, although the child argument of the addChildAt() method is specified as type DisplayObject, the argument must implement the IUIComponent interface to be added as a child of a container. All Flex components implement this interface.

The following example modifies the example in Example: Creating and removing a child of a VBox container. It uses the addChildAt() method to add the CheckBox control as the first child (index 0) of the VBox. It also has a Reorder children button that uses the setChildIndex() method to move a CheckBox control down the display list until it is the last the child in the VBox container. Boldface text indicates the lines that are added to or changed from the previous example.

<?xml version="1.0"?>
<!-- containers\intro\ContainerComponentsReorder.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">

    <mx:Script>
      <![CDATA[

        // Import the CheckBox and Alert classes.
        import mx.controls.CheckBox;
        import mx.controls.Alert;

        // Define a variable to hold the new CheckBox control.
        private var myCheckBox:CheckBox;
        
        // Define a variable to track if the CheckBox control 
        // is in the display list.
        private var checkBoxDisplayed:Boolean = false;
        
        public function addCB():void {  
            // Make sure the check box isn't being displayed.
            if(checkBoxDisplayed==false){
                // Create the check box if it does not exist.
                if (!myCheckBox) {
                    myCheckBox = new CheckBox();
                }
                // Add the check box as the first child of the VBox.
                myCheckBox.label = "New CheckBox";
                myVBox.addChildAt(myCheckBox, 0);
                checkBoxDisplayed=true;
            }
        }
    
        public function delCB():void {
            // Make sure a CheckBox control exists.
            if(checkBoxDisplayed){
                myVBox.removeChild(myCheckBox);
                checkBoxDisplayed=false;
            }
        }
        
        public function reorder():void {
        // Make sure a CheckBox control exists.
            if(checkBoxDisplayed==true){
                // Don't try to move the check box past the end 
                // of the children. Because indexes are 0 based, 
                // the last child index is one less
                // than the number of children.
                if (myVBox.getChildIndex(myCheckBox) < myVBox.numChildren-1)
                {
                    // Increment the checkBoxIndex variable and use it to 
                    // set the index of the check box among the VBox children. 
                    myVBox.setChildIndex(myCheckBox,
                        myVBox.getChildIndex(myCheckBox) + 1);
                }
            }
            else {
                Alert.show("Add the check box before you can move it");
            }
        }
      ]]>
    </mx:Script>

    <mx:VBox id="myVBox">
        <mx:Button label="Add CheckBox" click="addCB();"/>
        <mx:Button label="Remove CheckBox" click="delCB();"/>
        <mx:Button label="Reorder children" click="reorder();"/>
    </mx:VBox>
</mx:Application>

The executing SWF file for the previous example is shown below: