Building an Ajax Memory Tree in Oracle Application Express


by Scott Spendolini

 

Learn how to create an Ajax-based memory tree in Oracle Application Express, step by step. 

Published 2005

By now, you've probably heard of Ajax, which is shorthand for Asynchronous JavaScript and XML. If you've used Google Maps, Yahoo Mail, or Flickr, then you've seen the possibilities for creating a rich, interactive UI.

Ajax is not a technology itself, but rather a combination of several technologies—HTML, CSS, JavaScript, and XML—delivered via a Web page. Essentially, Ajax extends client-server-like functionality to the Web.

In this article, you will learn how to build an Ajax-based memory tree in Oracle Application Express (formerly HTML DB), based on any table that contains hierarchical data. (The code for the tree is based on the sample application provided by Application Express development team member Carl Backstrom. ) I have added the word "memory" to the name here as, unlike with Carl's example, this tree will "remember" which nodes are expanded, contracted, and selected across page views. There is also a search function that will locate any node in the tree and expand it accordingly—something that is not possible with the tree component supplied with Application Express. As the tree makes use of Ajax to fetch nodes as they are expanded, it can easily scale to support a table with thousands or more rows.

Requirements

  • Access to an Oracle Application Express 2.0 workspace
    You can quickly get access to such a workspace by either requesting a free workspace on http://apex.oracle.com, or by installing Oracle Database 10g Express Edition (XE) (Windows & Linux only). Note that prior versions (1.5 and 1.6) won't work.
  • A table with hierarchical data (ID, Parent ID, Name)
    If you do not have a table with data formatted in this manner, you can use the EMP demo table.

Step 1: Create the Required Table, Sequence, and Trigger

First, sign into your Application Express workspace and create the required database objects for the tree. The TREE_TEMP table will track which nodes of the tree are expanded for each user. It will be automatically and asynchronously populated each time a user clicks on the + or - icons in the tree via JavaScript and an application-level process.

From the SQL Workshop:

  1. Sign on with your Workspace Name, Username, and Password ( Username and Password only if using Oracle Database XE).
  2. Click on SQL Workshop.
  3. Click on SQL Commands.
  4. Copy and paste this code into the SQL region:

    create sequence tree_temp_seq start with 1
    

    and click on Run.

  5. Copy and paste this code into the SQL region:
    create table tree_temp
       (    temp_id number, 
                app_user varchar2(100), 
                app_session varchar2(100), 
                pid number, 
                id number, 
                name varchar2(100), 
                exp char(1), 
                icon varchar2(10)
       )    
    /
    

    and click on Run.

  6. Copy and paste this code into the SQL region:
    create or replace trigger tree_temp_bi
       before insert on tree_temp
       for each row
       declare      
             l_temp_id number;
       begin
             select tree_temp_seq.nextval
              into l_temp_id
              from dual;
             :new.temp_id := l_temp_id;
       end;
    /
    

    and click on Run.

Step 2: Create the Required View

The Ajax memory tree is based on a view rather than a table. For example:

create or replace force view tree_view
 (pid, id, name)
as      
select mgr pid, empno id, ename name from emp
/

The view you use must have only three columns and adhere to the following guidelines:

  • PID : The Parent ID of a node
  • ID : A unique identifier for a node
  • Name : Name to be displayed

The table must also have only one row where the PID is null. This will be the highest level node in the tree.

The tree you develop here will use the EMP table. Should you want to use your own table, adjust the CREATE VIEW procedure accordingly.

From the SQL Workshop:

  1. Copy and paste the CREATE VIEW code into the SQL region and click on Run.

Step 3: Install the Ajax_MEMORY_TREE Package

Next, create the Ajax_MEMORY_TREE package. This package contains all the logic that controls the tree.

  1. Copy and paste this code into the SQL region:
    create or replace package ajax_memory_tree
    is      
       procedure init;
       procedure render;
       procedure find_node (p_id in varchar2);
       procedure process_click;
       procedure contract;
       procedure expand;
    end ajax_memory_tree;
    /
    

    and click on Run.

  2. Copy and paste the code in Listing 1 into the SQL region and click on Run.

Step 4: Create an Application Express Application

Now that the required database objects are created, the next step is to create the Application Express application. If you already have an existing Application Express application, you can create your Ajax Memory Tree there.

  1. Click on Application Builder.
  2. Click on Create >.
  3. Select Create Application and click on Next >.
  4. Enter a Name for your Application, such as Ajax Memory Tree, and click on Next >.
  5. Add a Blank Page by clicking on Add Page and then clicking on Next >.
  6. Select One Level of Tabs and click on Next >.
  7. Select No for Copy Shared Components from Another Application and click on Next >.
  8. Take the defaults for Authentication Scheme, Language, and Use Language Preference Derived From and click on Next >.
  9. Select Theme 3 and click on Next >.
  10. Click on Create to create your application.

Step 5: Create Regions and Items

Next, create regions and items required for the tree. There are three regions required on Page 1:

  • JavaScript & CSS
    This region will hold the required JavaScript functions and a small in-line CSS or Style Sheet definition.
  • Ajax Memory Tree
    This region will simply call the ajax_memory_tree.render procedure, which in turn, will render the tree on the page.
  • Current Node
    This is a simple SQL Report that highlights the details of the selected node in the tree.
  1. Click on 1 - Page 1 to edit Page 1 in your Application.
  2. Create a new Region by clicking on the Add Region icon.

     

    Figure 1

     

  3. Select HTML and click on Next >.
  4. Select HTML again and click on Next >.
  5. Enter JavaScript and CSS for the Title, select No Template for the Region Template, and click on Next >.
  6. For the HTML Region Text Source, copy and paste the code from Listing 2 and click on Create Region.

This JavaScript comprises three functions that control the contracting and expanding of the tree, as well as the popup Find window:

  • popupNodeFinder
    This function will simply open a new popup window based on Page 2 of the application.
  • html_TooglePlusMinus
    This function, when called by getTreeNode, will toggle the + and - icon when clicked. It will also set the Application Express Item P1_BRANCH to the value of the item that was just clicked. Finally, it will asynchronously call one of the Application Level Processes—contractTree or expandTree—which, in turn, will update the tree_temp table.
  • getTreeNode
    This function is the core of the Ajax Memory Tree. Each time a + or - icon in the tree is clicked, this is the function which gets called. When executed, it will first call html_TogglePlusMinus, which will change the icon and set P1_BRANCH. Next, it will call the Application Process processClick and pass in the value of P1_BRANCH. The processClick process will, in turn, call the ajax_memory_tree.process_click procedure, which renders the newly expanded node and its siblings.

The embedded style sheet portion of this region is used to denote the currently selected node. When a node is selected, the selected_node style is applied to that node, thus giving it a light green background. All other nodes are rendered with the unselected_node style.

Next, create the region for the tree. This region will simply contain a PL/SQL call to the ajax_memory_tree package.render procedure.

  1. Create a new Region by clicking on the Add Region icon.
  2. Select PL/SQL Dynamic Content and click on Next >.
  3. Enter Ajax Memory Tree for the Title and click on Next >.
  4. For the PL/SQL Source, enter ajax_memory_tree.render; and click on Create Region.

In order for the tree to function, four items must also be added to this page. These items will store information such as the root node of the tree, which node was clicked, and the current node of the tree.

  1. Create a new Item by clicking on the Add Item icon.
  2. Select Hidden and click on Next >.
  3. Enter P1_TREE_ROOT for the Item Name, select Ajax Memory Tree as the Region, and click on Next >.
  4. Click on Create Item.
  5. Create a new Item by clicking on the Add Item icon.
  6. Select Hidden and click on Next >.
  7. Enter P1_SELECTED_NODE for the Item Name, select Ajax Memory Tree as the Region, and click on Next >.
  8. Click on Create Item.
  9. Create a new Item by clicking on the Add Item icon.
  10. Select Hidden and click on Next >.
  11. Enter P1_MESSAGE for the Item Name, select Ajax Memory Tree as the Region, and click on Next >.
  12. Click on Create Item.
  13. Create a new Item by clicking on the Add Item icon.
  14. Select Hidden and click on Next >.
  15. Enter P1_BRANCH_ID for the Item Name, select Ajax Memory Tree as the Region, and click on Next >.
  16. Click on Create Item.
  17. Create a new Item by clicking on the Add Item icon.
  18. Select Display Only and click on Next >.
  19. Select Display as Text (does not save state) and click on Next >.
  20. Enter P1_FIND for the Item Name, select Ajax Memory Tree as the Region, and click on Next >.
  21. For the Label, enter:
    <a href="#" onClick="popupNodeFinder ()";><img 
    src="/i/flashlight.gif" title="Find an Employee"></a> 
    
  22. For the Label Template, select Optional, and click on Next >.
  23. Click on Create Item.

Next, you'll need to create a simple report region. This report will display the data from the currently selected node in the tree.

  1. Create a new Region by clicking on the Add Region icon.
  2. Select Report and click on Next >.
  3. Select SQL Report and click on Next >.
  4. Enter Current Node as the Title, select 2 as the Column, and click on Next >.
  5. For the SQL Query, enter:
    select * from tree_view where id = :P1_SELECTED_NODE
    
    and click on Create Region.

Step 6: Create the Processes and Branch

In order to facilitate navigation and control of the tree, two page-level processes, three application-level processes, and a branch need to be created.

One of the page-level processes, Initialize the Tree, will only be called one time per session. This process will call the ajax_memory_tree.init procedure, which will clear the stale session information from the tree_temp table for the current user and set the root node of the tree.

The other page-level process, Find Node, is only executed when the Find Node popup window is called. This process will call the ajax_memory_tree.find_node procedure, passing in the node that the user selected. It will then render the tree with the specified node highlighted and the tree expanded accordingly.

  1. Under Page Rendering - Processes, add a new process by clicking on the Add Process icon.
  2. Select PL/SQL and click on Next >.
  3. Enter Initialize the Tree as the Name and click on Next >.
  4. For Enter PL/SQL Page Process, enter: ajax_memory_tree.init;
    and click on Next >.
  5. Leave the Success & Failure Messages blank and click on Next >.
  6. For Condition Type, select Value of Item in Expression 1 is NULL, enter P1_TREE_ROOT for Expression 1, and click on Create Process.
  7. Under Page Processing - Processes, add a new process by clicking on the Add Process icon.
  8. Select PL/SQL and click on Next >.
  9. Enter Find Node and click on Next >.
  10. For Enter PL/SQL Page Process, enter: ajax_memory_tree.find_node(:P1_SELECTED_NODE);
    and click on Next >.
  11. Leave the Success & Failure Messages blank and click on Next >.
  12. For Condition Type, select Request = Expression 1, enter FIND_NODE for Expression 1, and click on Create Process.

You need to create three application-level processes in order to support the asynchronous or Ajax portions of the tree. These processes will be called by JavaScript functions, which you previously added to the page.

For example, the JavaScript function getTreeNode will call the application-level process processClick and run it on Page 0 of the application:

htmldb_Get(null,&APP_ID.,'APPLICATION_PROCESS=processClick',0);
get.add('P1_BRANCH_ID',pValue);
gReturn = get.get();

Get more information on the htmldb_Get function here .

  1. In the Breadcrumb Menu, click on Application X, where X is the Application ID of your application.

     

    Figure 2

     

  2. Click on Shared Components.
  3. Under Logic, click on Application Processes.
  4. Click on Create > .
  5. Enter contractTree for the Name, select On Demand: Run this application process when requested by a page process and click on Next >.
  6. Enter: ajax_memory_tree.contract; for the Process Text and click on Next >.
  7. Click Create Process.
  8. Click on Create > .
  9. Enter expandTree for the Name, select On Demand: Run this application process when requested by a page process and click on Next >.
  10. Enter: ajax_memory_tree.expand; for the Process Text and click on Next >.
  11. Click Create Process.
  12. Click on Create > .
  13. Enter processClick for the Name, select On Demand: Run this application process when requested by a page process and click on Next >.
  14. Enter: ajax_memory_tree.process_click; for the Process Text and click on Next >.
  15. Click on Create Process.

Finally, you need to build an unconditional branch. This branch will redirect the application back to Page 1 unconditionally.

  1. Edit Page 1 by clicking the Edit Page icon in the upper-right corner of the page.

     

    Figure 3

     

  2. Create a new Branch by clicking on the Add Branch icon.
  3. Take the defaults and click on Next >.
  4. Enter 1 for Page and click on Next >.
  5. Click on Create Branch.

Step 7: Create Additional Pages

All the items and regions for the Ajax memory tree are placed on Page 1 of the application. However, two more pages required in order for the tree to function correctly.

  • Page 0 : In order for the Ajax components to work correctly, you need to create Page 0, which is a special page in Application Express. When the application- level processes run, they will run on Page 0. As Page 0 contains no logic, it is perfectly safe for the application processes to execute on that page, as no other business rules will be executed.
  • Search Page : Another standard page also needs to be created in order for the search functionality to work. This page can be any page number in Application Express. In this example, page 2 is used.
  1. On the Page Definition page, click on the Create > button, which is immediately to the right of the Edit Attributes button.

     

    Figure 4

     

  2. Select New Page and click on Next >.
  3. Select Blank Page and click on Next >.
  4. Enter 0 for the Page and click on Next >.
  5. Enter Page Zero for the Name and click on Next >.
  6. Select No for Would you like to use tabs for this new page? and click on Next >.Click on Finish.
  7. Click on Edit Page.
  8. On the Page Definition page, click on the Create > button, which is immediately to the right of the Edit Attributes button.
  9. Select New Page and click on Next >.
  10. Select Blank Page and click on Next >.
  11. Enter 2 for the Page and click on Next >.
  12. Enter Find Node for the Name and click on Next >.
  13. Select No for Would you like to use tabs for this new page? and click on Next >.
  14. Click on Finish.
  15. Click on Edit Page.

Step 8: Create Page 2 Regions

You need to create two regions on Page 2: one to hold the JavaScript needed to pass back the selected node to page 1, and another to hold a report on all items in the tree. You can customize this report later to include search functionality, should your tree contain more than just a few items.

  1. Create a new Region on Page 2 by clicking on the Add Region icon.
  2. Select HTML and click on Next >.
  3. Select HTML again and click on Next >.
  4. Enter JavaScript for the Title, select No Template for the Region Template and click on Next >.
  5. For the HTML Region Text Source, copy and paste this code:
    <script language="JavaScript">
            function passBack(passVal1, passVal2)
            {
            opener.document.getElementById("P1_SELECTED_NODE").value = passVal1;
            opener.document.getElementById("P1_MESSAGE").value = passVal2;
            window.opener.doSubmit('FIND_NODE');
            close();
            }
     </script>
    

    and click on Create Region.

  6. Create a new Region by clicking on the Add Region icon.
  7. Select Report and click on Next >.
  8. Select SQL Report and click on Next >.
  9. Enter Search for a Node as the Title and click on Next >.
  10. For the SQL Query, enter:

     

    select id, name, '[select]' pick from tree_view
    


    and click on Create Region.

When a user selects a node to view, the JavaScript function passBack must be called. This will pass back the selected ID to the original page and submit it. It will also trigger the Find Node process to be run.

  1. Click on the word Report next to your Report Region.
  2. Edit the Pick column by clicking on the corresponding Edit Icon.

     

    Figure 5

     

  3. Scroll down to the Column Link section.
  4. Enter #PICK# for the Link Text, select URL as the Target, and for the URL, enter

    javascript:passBack('#ID#','The current node is now #NAME# .')
    
  5. Scroll to the top of the page and click on Apply Changes.
  6. Click on Apply Changes again.

Step 9: Test Your Ajax Memory Tree

At this point, you have all the components required for the Ajax memory tree. All that is left is to test your application.

  1. In the Breadcrumb Menu, click on Application X, where X is the application ID of your application.
  2. Click on Run Application.
  3. Use the same username and password as you did to sign on to Application Express.
  4. Expand and/or contract each node by clicking on the + or - icon. Also, click on the names in the tree and verify that the Current Node report changes.

Your application should look similar to this:

 

Figure 6

 




Congratulations, you have just built an Ajax-based tree in Application Express!

For another, shorter example of how to expand Oracle HTML DB with Ajax, please see my blog entry here.

 


Scott Spendolini ( scott@sumnertech.com ) is President and Founder of Sumner Technologies, LLC ( www.sumnertech.com), a consulting firm specializing in Oracle Application Express.

 

Send us your comments