Filtering a Flex Tree using an ArrayCollection

Posted in ActionScript, Flex, How-To on January 6th, 2009 by Kalen Gibbons

Flex Trees can be difficult to filter because of their hierarchical nature. One possible way to do it is to use an ArraryCollection as your dataProvider, with each node having a “children” property that is also an ArrayCollection.

The tricky part in filtering the Tree is making sure the children are filtered in addition to the root nodes.  So, in the example below, I have created a function that will loop through each node and its children recursively.

It is important to note that the filtering takes place from the bottom up, meaning that a node’s children are always filtered before the node itself.  This is important, because normally a filter removes everything that does not match a certain criteria.  In our case, to remain in the collection, a node must match a certain criteria OR have children that do.

<?xml version=”1.0″ encoding=”utf-8″?>
<mx:Application xmlns:mx=”http://www.adobe.com/2006/mxml

layout=”absolute>


<mx:Script>

<![CDATA[
import vo.Person;
import mx.collections.ArrayCollection;

[Bindable]
private var people:ArrayCollection = new ArrayCollection([

new Person("Grandma Susan", new ArrayCollection([

new Person("John", new ArrayCollection([

new Person("Timmy"),
new Person("Sammy"),
new Person("Alan")

])),
new Person(“Tiffany“, new ArrayCollection([

new Person("Billy"),
new Person("Adam"),
new Person("Graham"),
new Person("Vennesa")

])),
new Person(“Michael“, new ArrayCollection([

new Person("Jannette"),
new Person("Alan", new ArrayCollection([

new Person("Alice"),
new Person("Jane")

]))

])),
new Person(“Peter“),

new Person(“Cindy“, new ArrayCollection([

new Person("Paul"),
new Person("David"),
new Person("Joseph"),
new Person("Cameron"),
new Person("Debra"),
new Person("Polly")

]))

]))

]);

private function refreshData():void{

//reset the root node to its original unfiltered data
people[0].children = new ArrayCollection(people[0].children.source);
//start the recursion at the root node
refreshRecursiveChildren(people.source[0]);
//update the Tree after the data has been filtered
personsTree.invalidateList();

}

private function refreshRecursiveChildren(person:Person):void{

if(person.children){

//loop through each child and filter its children
for each(var _person:Person in person.children.source){

refreshRecursiveChildren(_person);

}
//reset each “children” ArrayCollection to its original unfiltered data
person.children = new ArrayCollection(person.children.source);
//set the filterfunction for the newly updated node
person.children.filterFunction = filterData;
//run the fitlerFunction
person.children.refresh();

}

}

public function filterData(item:Object):Boolean{

//get the string to filter the nodes by
var searchString:String = iNameFilter.text;
//if string is found in node return true.
//since the recursive filtering takes place from bottom up, if
//a collection still has children after filtering, also return true

if(searchString.length == 0
|| item.name.toLowerCase().indexOf(searchString.toLowerCase()) >= 0)
return true;

else if(item.children != null && item.children.length > 0)

return true;

return false;

}
]]>

</mx:Script>

<mx:VBox width=”100%” height=”100%

paddingTop=”10
paddingBottom=”10
paddingLeft=”5
paddingRight=”5>
<mx:Tree id=”personsTree

dataProvider=”{people}
labelField=”name
width=”100%
height=”100%/>

<mx:HBox>

<mx:Label text=”Filter the Tree:/>
<mx:TextInput id=”iNameFilter” change=”refreshData()/>

</mx:HBox>

</mx:VBox>

</mx:Application>

You may right-click and select “View Source”
to view the full source code for the following example.


Tags: , , ,