Disabling a Tree Node in a Flex Tree Control

I was recently called upon to disable a selected node within a tree control.  While I encouraged the client to handle this issue on the server, and simply remove that node from the XML fed to the Tree, they preferred to have the node show, but simply not be selectable.  One thing which greatly assisted this task is the fact that the tree was required to begin showing completely open.  So, to start, i needed to build a method to loop over the data provider, and open each branch.  That looked like this.

function openTree(t:mx.controls.Tree) {
  var i:Number=0;
  var node:mx.controls.treeclasses.TreeNode=t.getTreeNodeAt(i);
  while (node != undefined){
    if (t.getIsBranch(node) && ! t.getIsOpen(node)){
      t.setIsOpen(node,true);
    }
    i++;
    node=t.getNodeDisplayedAt(i);
  }
}
Which simply loops over each node, and if it can be opened, opens it.

Next, we had to disable a node.  For this, I wrote a function like this:

function disableNode(node:Number){
  nav.rows[node]._alpha = 20;
  nav.rows[node].enabled = false;
  nav.rows[node].onPress = null;
}

The sad reality of this is that setting the enabled property didnt do much for us.  So, to make a node appear disabled, I I dimmed it by setting its alpha to 20, and I overrode its onPress event, which is what was being used to facilitate opening a node.

This solution works, so long as you know where in in the tree the node appears, since the index of the node differs, based on which branches are open, we were greatly aided by the requirement that the Tree was to begin open.   A final challange is that each time a branch is closed, the item rendered for the nodes within that branch are destroyed, and recreated when they open again.  To facilitate this, we implemented a bit of a hack.   We set a nodeOpen event for the tree, which opens all branches when any branch is opened, and then disables the selected nodes.

function openAndDisable(nodeToDisable:Number){
  openTree(nav);
  disableNode(nodeToDisable); 
}

When all pulled together a simplified test of this looks like this:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="
http://www.macromedia.com/2003/mxml" creationComplete="initApp()">
  <mx:Tree id="nav" dataProvider="{treedata}" nodeOpen="openAndDisable(4)"/>
  <mx:XML id="treedata">
    <top label="node 0">
      <row label="node 1"><leaf label="node 2"/></row>
      <row label="node 3"> <leaf label="node 4"/></row>
      <row label="node 5"><leaf label="node 6"/></row>
    </top>
  </mx:XML>
  <mx:Button click="disableNode(2)"/>
  <mx:Script>
    <![CDATA[
    function initApp(){
      openAndDisable(4);
    }
    function openAndDisable(nodeToDisable:Number){
      openTree(nav);
      disableNode(nodeToDisable); 
    }
    function disableNode(node:Number){
      nav.rows[node]._alpha = 20;
      nav.rows[node].enabled = false;
      nav.rows[node].onPress = null;
    }
    function openTree(t:mx.controls.Tree) {
      var i:Number=0;
      var node:mx.controls.treeclasses.TreeNode=t.getTreeNodeAt(i);
      while (node != undefined){
        if (t.getIsBranch(node) && ! t.getIsOpen(node)){
          t.setIsOpen(node,true);
        }
        i++;
        node=t.getNodeDisplayedAt(i);
      }
    }

 ]]>
</mx:Script>
</mx:Application>

All told, this is a bit of a hack.  A more bullet proof solution would be to build a cell renderer for the nodes of tree, and implement the ability to support an enabling/disabling there.  However, for our specific needs this time, the quick hack worked!

There are no comments.

Leave a Reply