There are many new AJAX functionalities included with CF8 and I am going to start to share some small things I have found useful. I will title these blog entries so they all start with "CF8 AJAX Features".

This first example shows a page that is using cflayout area "left" to display an html cftree that contains a hierarchical structure of categories (this could also apply to a page/sub page navigation system if you wanted to use cftree for that) and a cflayoutarea "center" that displays the child categories of the selected tree node.

For this example I have hard coded the category query so that you can see how it works without the need for a database table.

The challenge comes when you want to make it so that users can click on a link on the center cflayoutarea and have the selected tree node in the cftree change automatically to the new page.

Figuring this out took a decent amount of research into the YUI TreeView object and then some real digging into how the folks at Adobe implemented it.

From Adobe documentation I found there was a ColdFusion.Tree.getTreeObject() function I could use to the access tree object, and then they kindly directed me to the Yahoo documentation to figure the rest out myself.

After reading the DOM for the TreeView object (http://developer.yahoo.com/yui/docs/YAHOO.widget.TreeView.html) I found the function getNodeByProperty() which I was certain was what I needed to dynamically find the correct tree node from the body page based on the category_id column in my query. However, I had no idea what ColdFusion named the property when it created the tree object. I had started with the obvious and tried getNodeByProperty('value',catID) but unfortunately they did not chose to make it that easy for me. so I found some javascript online that recursively dumped each property in a javascript object and pops it up in an alert page and used that to figure out that the "value" attribute in my cftreeitem tags was put into the "id" property in the Yahoo node objects. After I figured that out, it all came together like an "A-Team" plan.

Here is an example of how to do it:

Save this code as myLayout.cfm

<!--- I am building a query here but normally this would be a query against a categories table --->
<cfset getcategories = querynew("category_id,Name,ParentID")>
<cfset queryaddrow(getcategories)>
<cfset querysetcell(getcategories,"category_id","1")>
<cfset querysetcell(getcategories,"Name","Category1")>
<cfset querysetcell(getcategories,"ParentID","0")>
<cfset queryaddrow(getcategories)>
<cfset querysetcell(getcategories,"category_id","2")>
<cfset querysetcell(getcategories,"Name","Category2")>
<cfset querysetcell(getcategories,"ParentID","1")>
<cfset queryaddrow(getcategories)>
<cfset querysetcell(getcategories,"category_id","3")>
<cfset querysetcell(getcategories,"Name","Category3")>
<cfset querysetcell(getcategories,"ParentID","1")>
<cfset queryaddrow(getcategories)>
<cfset querysetcell(getcategories,"category_id","4")>
<cfset querysetcell(getcategories,"Name","Category4")>
<cfset querysetcell(getcategories,"ParentID","0")>



<!--- Here is where all the magic happens the trick was figuring out that the
   "value" attribute in the cftreeitem tag corresponds to the "id" property in the
   YAHOO.widget.TreeView.getNodeByProperty() function. That took some digging
   but I found it.   
--->

<script language="JavaScript">
function catTreeNodeSelection(catID){
   tree = ColdFusion.Tree.getTreeObject("categorytree");
   me = tree.getNodeByProperty('id',catID);
   me.parent.expand();
   me.tree.fireEvent("labelClick", me);
}
</script>

<!--- cfajaximport is needed so the cftree will work withing the layoutarea --->
<cfajaximport tags="cftree">

<cflayout type="Border" name="toplevellayout" style="margin:0px;height:400px;">
<cflayoutarea
       position="left"
      name="treepanel"
      title="Document Categories"
      size="250"
      style="padding-top:3px;"
      overflow="auto"
      collapsible="false"
      splitter="true"
      minsize="200">

      
      <cfform>
         <cftree name = "categorytree" font = "Arial Narrow" italic="yes" completepath="no" format="html">
         <cftreeitem value="0" display="Show All Documents" parent="categorytree" imgopen="folder">
            <cfloop query="getcategories">
               <cftreeitem
                  value="#getcategories.category_id#"
                  display="#getcategories.name#"
                  parent="#getcategories.ParentID#"
                  img="folder"
                  imgopen="folder"
                  expand="no">

            </cfloop>
         </cftree>
      </cfform>
      
</cflayoutarea>
   
<cflayoutarea position="center" name="documentwindow" overflow="hidden">
          <!--- I'm using a URL binding on this cfdiv and passing the selected category
               tree node so that when a new node is selected the div content --->

<cfdiv bind="url:display.cfm?category_id={categorytree.node}"/>
</cflayoutarea>
</cflayout>

then save the following code as display.cfm:

<cfparam name="url.category_id" default="0">
<cfif url.category_id eq ""><cfset url.category_id = 0></cfif>

<!--- Again, I am building a query here but normally this would be a query against a categories table
   and in reall life you would probably add a where clause on this page to only get the categories
   where parentID = #url.categoryID# but my cfif later takes care of that for me and this is just
   a demo so whatever. --->

<cfset getcategories = querynew("category_id,Name,ParentID")>
<cfset queryaddrow(getcategories)>
<cfset querysetcell(getcategories,"category_id","1")>
<cfset querysetcell(getcategories,"Name","Category1")>
<cfset querysetcell(getcategories,"ParentID","0")>
<cfset queryaddrow(getcategories)>
<cfset querysetcell(getcategories,"category_id","2")>
<cfset querysetcell(getcategories,"Name","Category2")>
<cfset querysetcell(getcategories,"ParentID","1")>
<cfset queryaddrow(getcategories)>
<cfset querysetcell(getcategories,"category_id","3")>
<cfset querysetcell(getcategories,"Name","Category3")>
<cfset querysetcell(getcategories,"ParentID","1")>
<cfset queryaddrow(getcategories)>
<cfset querysetcell(getcategories,"category_id","4")>
<cfset querysetcell(getcategories,"Name","Category4")>
<cfset querysetcell(getcategories,"ParentID","0")>

<cfoutput>
<b>Your are viewing Category #url.category_id#</b><br>
Below are the child categories(if any):<br>
<table>
<cfloop query="getcategories">
<cfif getcategories.parentID eq url.category_id>
<tr>
<td><img src="/CFIDE/scripts/ajax/resources/cf/images/FolderClose.gif" alt="" width="24" height="24" border="0"></td>
    <!--- Here is where I call the function that is in the main layout page. --->
    <td><a href="javascript:catTreeNodeSelection('#getcategories.category_id#')">#getcategories.Name#</a></td>
</tr>
</cfif>
</cfloop>
</table>
</cfoutput>

Comments (Comment Moderation is enabled. Your comment will not appear until approved.)
Dave's Gravatar Hi scott. I see how you bound the tree node value to the catergoy_id and passed it using url:, but is it possible to bind the node value to a variable for use in the same form or on a cflayout area on the same page without using cfdiv. I think hanging issue that I'm seeing with the tree is being caused by passing the bind="url:..." to another page. I just want to try it locally before I really start going nutts. thanks
- Dave
# Posted By Dave | 9/9/08 10:33 AM
Dave's Gravatar Nevermind, duh! I swear I tried it last night and it didnt work but I figured it out. thanks.
# Posted By Dave | 9/9/08 12:45 PM
mathijs's Gravatar wow thanks! this helped me a lot!!!!
# Posted By mathijs | 10/28/08 5:43 PM