Binding Linear data to Tree Components
Flex 2.0 Tree component is a great way to show hierarchical data. The ease of expanding and minimizing nodes makes organizing and visualization easy. A few examples in which it can be use will be in Email application (where you can organise the folder structures) and Instant Messenger application (where you can bind the roster list to it) .
However, many a times, the data we receive are linear. Which means they are best to be used with components like ComboBox, List and Menus, etc, but not with Tree. In this article, I will discuss on how we can format a Linearly structured piece of information into a hierarchical data, and allow for databinding with a Tree component.
For example, this is the piece of information you receive.
1 2 3 4 5 6 7 8 9 | <iq id="roster_6" to="sj1@vserver/XIFF" type="result"> <query xmlns="jabber:iq:roster"> <item jid="residentevil_6440yahoo.com@msn.vserver" subscription="both" name="friend"> <group>Friends</group> </item> <item jid="msn.vserver" subscription="both" name="MSN Transport"> <group>Transports</group> </item> </query></iq> |
The preceding XML is a sample xml from an Openfire server on XMPP specification. What its does is that it tells me that I have 2 buddies in my contact list. Now, this is easy if I want to bind it to a List isn’t it? A 5 minute work will do. But what if I want to sort it according in alphabetical order, bind it according to the changes (a user might get online, offline, and change his/her displayname after all), and most important, display it hierarchically according to the Groups they are in? The answer will be Tree component.To bind a linear data to a Tree Component, we will need several steps
1) The linear data converted to a ArrayCollection
2) Create a class, say TreeCollection that inherites from ArrayCollection, and it will listen to the original ArrayCollection ‘CollectionEvent.COLLECTION_CHANGE’ event.
3) On the change event, it will sort internally into the Tree format
4) Binding the Tree format to the TreeCollection
1) Let us start by creating an ArrayCollection consisted of the following:
1 2 3 4 5 6 | var array:ArrayCollection = new ArrayCollection([ {label:"dog", group:"Animal"}, {label:"orange", group:"Fruits"}, {label:"cat", group:"Animal"}, {label:"apple", group:"Fruits"}]) |
2) Next, create a class that inherits from an ArrayCollection
1 2 3 4 5 6 7 8 9 10 11 12 | public class TreeCollection extends ArrayCollection{ public function TreeCollection(base:ArrayCollection):void { super(null); base.addEventListener(CollectionEvent.COLLECTION_CHANGE,on_collection_change); } private function on_collection_change(e:CollectionEvent):void{} } |
As you can see, the TreeCollection will hold the original collection and listen to the collection change event.
3) Now, we need to sort the original collection. The implementation can change depending on different application business logic. In this case, I will sort it according to the groups attribute.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | private function on_collection_change(e:CollectionEvent):void{ sortItem(e.items) } private function sortItem(e:Array):void { for(var i:Number = 0 ; i < e.length ; i++) { var item:Object = e[i]; if(item.group != null) { if(internal_hashmap[item.group]){ var temp_group:Object = internal_hashmap[item.group] var added:Boolean = false for(var j:Number = 0;j < temp_group.children.length ;j++){ if(temp_group.children[j].label ==item.label) { added = true temp_group.children.setItemAt(item, j) break; } } if(!added) temp_group.children.addItem(item) } else { var temp_obj = internal_hashmap[item.group] = new Object(); temp_obj.label = item.group temp_obj.children = new ArrayCollection(); temp_obj.children.addItem(item) this.addItem(temp_obj); } } } } |
Finally, sort the item when the TreeCollection is first initialize :
1 2 3 4 5 6 7 | public function TreeCollection(base:ArrayCollection):void{ super(null);internal_hashmap = new Object(); sortItem(base.source); base.addEventListener(CollectionEvent.COLLECTION_CHANGE, on_collection_change); } |
4) Now, for the final mxml:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | <mx:application xmlns:mx="http://www.adobe.com/2006/mxml"> layout="absolute" applicationComplete="onInit()" > <mx:tree id="myTree" labelfield="label"></mx:tree> <mx:script> <!--[CDATA[ import com.fug.demo.TreeCollection; import mx.collections.ArrayCollection; function onInit() { var array:ArrayCollection = new ArrayCollection([{label:"dog", group:"Animal"}, {label:"orange", group:"Fruits"}, {label:"cat", group:"Animal"}, {label:"apple", group:"Fruits"} var tree:TreeCollection = new TreeCollection(array); myTree.dataProvider = tree; array.addItem({label:"mouse", group:"Animal"}) } ]]--></mx:script> </mx:application> |
There you go, a linear ArrayCollection is now mapped to a Tree Component.Download the source here:
http://fug.sg/p/DemoTreeCollection.zip
Next up: Using ItemRenderer with Tree Component
Sphere: Related Content



