Dynamically adding new children to a Flex Accordion container

by Peter deHaan on September 18, 2007

in Accordion, AddChild

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.

{ 18 comments… read them below or add one }

1 Samus_ October 10, 2007 at 11:38 am

hello, citing from http://livedocs.adobe.com/flex/201/langref/mx/states/RemoveChild.html

“The RemoveChild class removes a child display object, such as a component, from a container as part of a view state. The child is only removed from the display list, it is not deleted.”

this will surely lead to memory leaking problems, and also forces me to reset the control’s contents each time they’re shown, how can I destroy a component?

Reply

2 Samuel Neff November 2, 2007 at 9:10 pm

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

Reply

3 Samus_ November 7, 2007 at 5:27 pm

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!

Reply

4 Samus_ November 7, 2007 at 6:14 pm

UPDATE: I’ve checked again that link and the links suggested there, there is a way to add the listeners as “weak references” that are ignored by the garbage collector; very interesting, that solves half of my problem of lost references.
check it here: http://www.adobe.com/devnet/flashplayer/articles/resource_management.html and here: http://www.gskinner.com/blog/archives/2006/07/as3_weakly_refe.html

Reply

5 danny December 15, 2007 at 2:35 pm

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!

Reply

6 djrogi February 29, 2008 at 11:34 pm

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

Reply

7 PaulH March 9, 2008 at 5:42 pm

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” ;-)

Reply

8 peterd March 9, 2008 at 9:32 pm

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

Reply

9 Kirk October 2, 2008 at 3:07 pm

Paul:

Will the same code work to dynamically add a tab to a tabnavigator container?

Kirk

Reply

10 peterd October 2, 2008 at 11:25 pm

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

Reply

11 jm February 6, 2009 at 8:09 am

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

Reply

12 Jose May 3, 2009 at 4:00 pm

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

Reply

13 Michael July 2, 2009 at 7:11 am

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?

Reply

14 Nicolas November 18, 2009 at 4:42 pm

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?

Reply

15 Nicolas November 18, 2009 at 5:21 pm

Solved!

//Removes all previous children from accordion
var numChildren:Number = accordion.numChildren
for(var i:Number=0; i<numChildren; i++){
		accordion.removeChildAt(i);
}

Reply

16 Nicolas November 20, 2009 at 4:59 am

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);
}

Reply

17 Peter deHaan November 20, 2009 at 8:08 am

@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

Reply

18 Igor January 1, 2010 at 7:01 am

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.

Reply

Leave a Comment

Sorry, this blog is terrible at eating HTML comments.
If you're pasting any HTML/XML/MXML code, you need to convert your < characters to &lt; and your > characters to &gt; .

You can use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="">

Anti-Spam Protection by WP-SpamFree

Previous post:

Next post: