Dynamically adding new children to a Flex Accordion container

The following example shows how you can add and remove children from a Flex Accordion container by using the addChild() and removeChild() methods.

Full code after the jump.

View MXML

<?xml version="1.0" encoding="utf-8"?>
<!-- http://blog.flexexamples.com/2007/09/18/dynamically-adding-new-children-to-a-flex-accordion-container/ -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
        layout="vertical"
        verticalAlign="middle"
        backgroundColor="white">

    <mx:Script>
        <![CDATA[
            import mx.containers.VBox;

            private const MAX_CHILDREN:uint = 5;

            private function accordion_addChild():void {
                if (accordion.numChildren < MAX_CHILDREN) {
                    var vbox:VBox = new VBox();
                    vbox.label = "child " + accordion.numChildren;
                    vbox.percentWidth = 100;
                    vbox.percentHeight = 100;
                    var randColor:uint = Math.random() * 0xFFFFFF;
                    vbox.setStyle("backgroundColor", randColor);
                    accordion.addChild(vbox);
                }
            }

            private function accordion_deleteChild():void {
                if (accordion.selectedChild) {
                    accordion.removeChild(accordion.selectedChild);
                }
            }
        ]]>
    </mx:Script>

    <mx:ApplicationControlBar dock="true">
        <mx:Button label="Add child"
            click="accordion_addChild();" />
        <mx:Button label="Delete child"
            click="accordion_deleteChild();" />
    </mx:ApplicationControlBar>

    <mx:Accordion id="accordion" width="240" height="160" />

</mx:Application>

View source is enabled in the following example.

19 thoughts on “Dynamically adding new children to a Flex Accordion container

  1. Samus,

    The component is destroyed just like any other class–when it is not accessible from the application (when all references are destroyed). Having a parent is a reference so being on the display list by definition keeps something alive. Having a reference to the component such as an instance variable also could keep it alive.

    In the above example, however, the component is created as a function-local variable and added to the accordion. No other reference is kept so in this situation, the component is eligible for garbage collection when it’s removed from the display list.

    HTH,

    Sam

  2. hi thanks for the reply! yes reading a little more seems that objects are destroyed when there’s no other reference to them, that reminds me of files in a unix filesystem; is quite tricky to me honestly I didn’t expected something like that because this forces me to keep track of references to the objects and it seems that event listeners also apply as references, perhaps you could suggest me some design patterns that are better to deal with this situation (I’m more used to the C approach and never worked in Java). I’m most worried about leaking memory because I left some references somewhere else :/ also I’ve found an interesting article about the garbage collectos itself here: http://www.adobe.com/devnet/flashplayer/articles/garbage_collection.html c’ya!

  3. hey, what if I wanted to put the add and remove functions into there own class? when i do that, it says that “accordian.addchild…” is undefined. I’m trying to learn how to make my code more modular, and if someone could explain this it would be very helpful. thanks!

  4. on a dynamically created accordion like this, how would you create a DataGrid that pulls from live data? Been working on it for about 3 days now, and get stumped by adding a child under a child.

    Awesome examples they are a huge help to new Flex-ers

  5. peter,

    what about the contents of the remaining children? i’ve got an accordion setup in mxml that i reconfigure by deleting children. what i’m seeing is the contents of the remaining children (all List) aren’t getting rendered until the user changes the selectedIndex. i’ve tried pretty much all the tricks i know to get the List contents to render after deleting the child (creationPolicy, etc.) but no luck.

    any ideas?

    ps: i guess no need to keep repeating how much we love this blog, but what the heck, “we love this blog” ;-)

  6. PaulH,

    Apart from setting the creationPolicy property, I don’t have any other immediate ideas. And you tried setting the creationPolicy to “all”, or setting it to “auto” then “all”?

    If you think it is a bug, file it at http://bugs.adobe.com/flex/ and solicit a few votes and then somebody at Adobe can take a look.

    Peter

  7. Kirk,

    The same general code should work for TabNavigator:

    <?xml version="1.0" encoding="utf-8"?>
    <mx:Application name="TabNavigator_addChild_test"
            xmlns:mx="http://www.adobe.com/2006/mxml"
            layout="vertical"
            verticalAlign="middle"
            backgroundColor="white">
    
        <mx:Script>
            <![CDATA[
                import mx.containers.HBox;
    
                private function addChildButton_click(evt:MouseEvent):void {
                    var box:HBox = new HBox();
                    box.label = "Child " + tabNavigator.numChildren;
                    box.percentWidth = 100;
                    box.percentHeight = 100;
                    box.setStyle("backgroundColor", int(Math.random() * 0xFFFFFF));
                    tabNavigator.addChild(box);
                }
    
                private function removeChildButton_click(evt:MouseEvent):void {
                    if (tabNavigator.selectedChild != null) {
                        tabNavigator.removeChild(tabNavigator.selectedChild);
                    }
                }
    
                private function removeAllChildrenButton_click(evt:MouseEvent):void {
                    tabNavigator.removeAllChildren();
                }
            ]]>
        </mx:Script>
    
        <mx:ApplicationControlBar dock="true">
            <mx:Button id="addChildButton"
                    label="Add child"
                    click="addChildButton_click(event);" />
            <mx:Button id="removeChildButton"
                    label="Remove child"
                    click="removeChildButton_click(event);" />
            <mx:Button id="removeAllChildrenButton"
                    label="Remove all children"
                    click="removeAllChildrenButton_click(event);" />
        </mx:ApplicationControlBar>
    
        <mx:TabNavigator id="tabNavigator"
                width="100%"
                height="100%" />
    
    </mx:Application>
    

    Peter

  8. Hi

    I have an application with a viewStack to separate my screens.
    Everything works fine in the first screen, but in the second one, i
    cannot call an ActionScript function in the show event of a VBox
    container

    I am assuming that when the second view is activated the show event of
    the inner elements is called, but apparently i am mistaken. The
    creationComplete event is valid for the first screen because it is
    called when the application starts, but not for the second screen
    elements because they are already created

    Please help

  9. Hi,

    I need to add to a child from other children already created.

    Example:

    acGrupos.selectedChild.addChild(cmb1);

    The idea is that this new child is within the selected.

    Thanks

  10. is there a way to assign a unique “id” to each of the new children? And if this is possible, how would you reference those children later in the program with their unique ids?

  11. Navigating away to another state does not destroy the Accordion. When I come back again it is appending new children instead of starting from an empty accordion. Bizar? I was always under the impression that leaving a state removes that screen.
    (maybe that was what was meant by Garbage collection)
    Is there a way to rest the accordion so that it is empty?

    1. Solved!

      //Removes all previous children from accordion
      var numChildren:Number = accordion.numChildren
      for(var i:Number=0; i<numChildren; i++){
      		accordion.removeChildAt(i);
      }
  12. Interesting. This only works if you countdown like removing items off a stack otherwise it causes an error. I didn’t notice it until I had more than two items.
    It makes sense now. As the number of children decreases the indexes change.

    //Removes all previous children from accordion
    var numChildren:Number = accordion.numChildren
    for(var i:Number=numChildren - 1; i > -1; i--){
    	accordion.removeChildAt(i);
    }
    1. @Nicolas,

      Kind of makes sense. If you have two children and then you call accordion.removeChildAt(0);, then you’re left with one child, which moves to the 0 position. So when you call accordion.removeChildAt(1); you’d get an error since the child formerly at 1 has moved to 0. You could either go in reverse like your example, or you could probably just do a loop and always remove the child at the 0 position. Or, you may be able to just set the Accordion container’s data provider to an empty array and remove all the children at once.

      Peter

  13. Has anyone noticed that when clicking on the header and animation run, right border of Accordion flickers, I came to the conclusion that this is due to the fact that in AS code we use the properties percentHeigth and percentWidth, if you add child in MXML, then this is no flicker.

Comments are closed.