Auto select New Item in Tree component

There are plenty examples out there on how to add and remove leaf nodes from a Tree control at run time, one of my favorite is Working with tree controls tutorial by Adobe.

Now it’s time to learn more advanced stuff: auto select for new created item. This would be very easy to accomplish with List control. You would probably use ArrayCollection as a dataProvider, call addItem(item:Object), keep track of that item index, and then use list.selectedIndex = index. 

Unfortunately this is not easy with Tree control. Tree control could have opened and closed nodes. If the nodes in the tree control are collapsed, the selectedIndex is different than when all the nodes are expanded. Instead of using selectedIndex you want to loop through all nodes to find a new item’s index.


Get Flex Builder for free if you are an unemployed developer

<?xml version="1.0" encoding="utf-8"?>
<mx:Application
    xmlns:mx="http://www.adobe.com/2006/mxml"
    layout="absolute"
    creationComplete="onCreationComplete()" viewSourceURL="srcview/index.html"> 

    <mx:Script>
        <![CDATA[
            import mx.collections.XMLListCollection;
            []
            private var company:XML =
              <node>
                <node label="Finance" code="200">
                    <node label="John H"/>
                    <node label="Sam K"/>
                </node>
                <node label="Operations" code="400">
                    <node label="Bill C"/>
                    <node label="Jill W"/>
                </node>
                <node label="Engineering" code="300">
                    <node label="Erin M"/>
                    <node label="Ann B"/>
                </node>
              </node>;

            []
            private var companyData:XMLListCollection = new XMLListCollection(company.children());

            private function removeNode():void
            {
                var node:XML = XML(tree.selectedItem);
                if(node == null) return;

                var children:XMLList = XMLList(node.parent().children());
                for(var i:int=0; i<children.length(); i++)
                {
                    if(children[i].@label == node.@label)
                    {
                        delete children[i];
                    }
                }
            } 

            private function addNode():void
            {
                var node:XML = <node/>;
                node.@label = folderNameInput.text;

                var parentNode:XML;
                if(tree.selectedItem == null)
                    companyData.addItem(node);
                else
                {
                    parentNode = XML(tree.selectedItem);
                    parentNode.appendChild(node);
                    tree.expandItem(parentNode, true);
                }
                folderNameInput.text = '';
                selectNode(node);
            } 

            private var _index:int;
            private var _isFounded:Boolean = false;
            private function selectNode(node:XML):void
            {
                _isFounded = false;
                _index = -1;
                for each(var parentNode:XML in companyData)
                {
                    if(tree.isItemOpen(parentNode))
                        loopAndFindXml(node, parentNode);
                    else if(!_isFounded)
                        _index++;
                }
                tree.selectedIndex = _index;
            } 

            private function loopAndFindXml(node:XML, parentNode:XML):void
            {
                if(_isFounded)
                    return;
                _index++;
                //trace('myNode , '+_index+' , '+parentNode.toXMLString());

                for(var i:int=0; i<parentNode.children().length(); i++)
                {
                    if(_isFounded)
                        return;

                    if(tree.isItemOpen(parentNode.node[i]))
                    {
                        //trace('loop');
                        loopAndFindXml(node, parentNode.node[i]);
                    }
                    else
                    {
                        if(_isFounded)
                            return;
                        _index++;
                        //trace('myNode1 '+_index+' , '+parentNode.node[i].toXMLString());

                        if(parentNode.node[i] == node)
                        {
                            //trace('found');
                            _isFounded = true;
                            return;
                        }
                    }
                }
            } 

            private function expandAllTreeNodes(tree:Tree):void
            {
                tree.expandChildrenOf(company, true);
            } 

            private function onCreationComplete():void
            {
                expandAllTreeNodes(tree);
            } 

        ]]>
    </mx:Script> 

    <mx:Tree id="tree"
        x="8" y="40"
        dataProvider="{companyData}"
        labelField="@label"
         width="162" height="245"
    /> 

    <mx:TextInput id="folderNameInput"
        x="10" y="11"
    /> 

    <mx:Button
        x="178" y="11"
        label="Add Node"
        width="112"
        click="addNode()"
    /> 

    <mx:Button
        x="178" y="41"
        label="Remove Node"
        click="removeNode()"
     width="112"/> 

</mx:Application>

View the Live Demo (right click to view the source)

3 Comments


  1. Steffen Franke
    July 21, 2009 at 4:03 pm

    Hi, good work, it helped me alot, thanks for sharing!

    -Steffen

  2. Sam P
    May 23, 2010 at 8:23 am

    Thanks. Just what I needed too. Nice job.

  3. Ganga
    June 25, 2010 at 11:30 am

    Thank you. it helped me lot.

Leave a comment