Thursday, November 18, 2004 My foray into the Macromedia Flex Tree control (cont.)

Step 6: Dynamic Functionality

The basics work, so now I want to tie it to a database to make it dynamic, pulling data from the database and sending new links to the database. While there are many possible ways to do this in Flex, I know how to do this easily with Access databases and ColdFusion components as Web Services so that's how I went. I created my Access database and a CFC to use as a Web Service then called the service in Flex. I'm still rusty with ColdFusion, so my examples here, while functional, may not be the best.

links.mdb DSN:links
LinkID (Autonumber)Category (Text)Description (Text)URL (Text)
0KidsDisney Kidshttp://www.disneykids.com
1ProgrammingPlanet Source Codehttp://www.planet-source-code.com
linkdata.cfc
<cfcomponent>
   <cffunction name="getLinks" returntype="query" access="remote" output="false">
      <cfquery name="qryLinks" datasource="links">
         SELECT * 
         FROM tblLinks
         ORDER BY Category;
      </cfquery>
      <cfreturn qryLinks />
   </cffunction>
</cfcomponent>

When we process the Web Service, we receive back a Query as the result, not an XML tree. Unlike an mx:DataGrid, we can't simply bind the query to the mx:Tree and have it work, we have to process the data.Thanks to Ben Forta's great Flex/CFC Dashboard2 example and Dimitrios Gianninas' information on looping through a query, I created a query2tree function to process the query.

query2tree.as
// Turn a CF query into Flex tree XML
function query2tree(src) {
   // Define tree object
   var tree:XML = new XML();
   var curCategory:String="";
   for( var i = 0; i < src.length; i++ ) {
      if (src[i].CATEGORY != curCategory) {
         // if not first category, append last node
         if (i != 0) tree.appendChild(node);
         // New category
         var node:XMLNode=tree.createElement('node');
         curCategory=src[i].CATEGORY;
         node.attributes['label']=src[i].CATEGORY;
      }
      // add leaves
      var leaf:XMLNode=tree.createElement('node');
      leaf.attributes['label']=src[i].DESCRIPTION;
      leaf.attributes['nodeURL']=src[i].URL;
      node.appendChild(leaf);
   }
   tree.appendChild(node); // append last node
   // Return complete XML tree
   return tree;
}

Then at last we add the Script and Web Service to our Flex file, call the web service on initialization of our Tree, then bind our processed result to the Tree's data provider.

links.mxml
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.macromedia.com/2003/mxml">
   <mx:WebService id="svcLinks" wsdl="http://localhost:8500/linkdata.cfc?wsdl" fault="alert('Error: ' + event.fault.faultstring,'Error')" showBusyCursor="true">
      <mx:operation name="getLinks" />
   </mx:WebService>
   <mx:Binding source="query2tree(svcLinks.getLinks.result)" destination="treLinks.dataProvider"/>
   <mx:Script source="query2tree.as"/>
   <mx:Script source="linkfunc.as"/>
   <mx:Panel height="100%" title="My Links" fontSize="18">
      <mx:Tree initialize="svcLinks.getLinks.send()" id="treLinks" change="loadPage(event);" fontSize="10" defaultLeafIcon="@Embed('leaf.png')">
      </mx:Tree>
      <mx:ControlBar>
         <mx:VBox horizontalAlign="right" fontSize="10">
            <mx:FormItem label="URL">
               <mx:TextInput width="250" id="txtURL"/>
            </mx:FormItem>
            <mx:FormItem label="Description" required="false">
               <mx:TextInput width="250" id="txtDescription"/>
            </mx:FormItem>
            <mx:FormItem label="Category">
               <mx:ComboBox width="200" id="cboCategory"/>
            </mx:FormItem>
            <mx:Button label="Add Link"/>
         </mx:VBox>
      </mx:ControlBar>
   </mx:Panel>
</mx:Application>

Previous | Next


References:

2: Ben Forta's ColdFusion and Flex Dashboard