Press "Enter" to skip to content

APEX 5.0 Converting to the new APEX Tree

Today I’ll show step by step how to convert from the old APEX tree region, which used the third party jsTree library, to the new APEX 5.0 tree implementation. As I previously mentioned the tree region now uses the same JavaScript tree view widget that is used in Page Designer by default. But if you have an old application that is using the tree region it will continue to use the old jsTree region after upgrading to 5.0.

The reason that the tree region couldn’t be automatically switched to the new tree during upgrade is because of differences in how the implementations use icons/images and complex ways in which customers have customized it with JavaScript by calling jsTree APIs.

This is an update of what I presented at a Boston APEX Meetup last October.

For this tutorial I’ll use the 4.2 version of the Sample Trees application. If you have an instance of APEX running 4.2 you can export a copy of the Sample Trees application. If not you may be able to follow along with a tree region from one of your own apps (make a copy or backup first).

After installing the Sample Trees application run it (from Application Builder) and click on Project Tracking Example. The old tree will look like this.

Old APEX tree

Note: You may find that there is a JavaScript error on this page. I think this may happen because of changing ids between export and import. On that page there is some Execute when Page Loads code that tries to expand the tree but it uses a hard coded id. It may look something like this:

javascript:apex.widget.tree.expand_all('tree2515644422834949124');
Just delete this code.

At this point notice the old fashion style such as dotted lines and tooltips. Also notice that it is very difficult to use the tree with the keyboard. All you can do is tab through all the links. Because jsTree is incompatible with the newer version of jQuery that APEX 5.0 uses the jQuery Migrage plugin must be included on the page. APEX takes care of adding jQuery Migrate automatically if the old tree is used.

Step 1. Change tree implementation

Click on Quick Edit in the Developer Toolbar, hover over the tree so that it has a blue box around it and click. This will bring you to the Page Designer ready to edit the tree on page 3. If you have not used Page Designer before you may want to take a look at this video overview.

In the Rendering tree the Task Tree node should be selected. Select the Attributes child node. In the property editor on the right side you will see the Tree Implementation property. Change it to APEX Tree.

Click the Save and Run button.

Save and Run

You can now see that it is using the new tree. The style has changed. It still has tooltips but they are using the new jQuery UI tooltips rather than the jsTree ones. Notice that it is keyboard accessible. It occupies a single tab stop and the arrow keys move up and down and also expand or collapse nodes. You can also use the Page Up/Down, Home and End keys and type the first letter of the node you want to go to. The Collapse and Expand buttons still work. But the icons are missing so we will fix that next

New Tree but no icons

Step 2 Updating the icons

The old jsTree library used individual image files for the tree node icons. APEX 5.0 uses CSS based icons in most places including the tree view. CSS based icons are much more efficient. This works by specifying two classes. One is the icon type, which is used to distinguish between kinds or sources of icons such as font icons like Font Awesome or your own CSS sprites. The second class identifies the specific icon within the type. For this demonstration I’ll be using Font Awesome. I have already picked out some icons that were a close fit to what was previously used.

Click Quick Edit and click on the tree again to go back to page designer.

The icons to use are specified as part of the SQL query. Click the Code Editor button on the SQL Query property.

Code Editor Button

This brings up the Code Editor. Change the following lines


       case when item_type = 'P' then '#IMAGE_PREFIX#menu/blue_function_16x16.gif' 
            when item_type = 'S' then '#IMAGE_PREFIX#menu/minus-small.png'
            when item_type = 'T' then '#IMAGE_PREFIX#menu/go-small.png'

to


       case when item_type = 'P' then 'fa-file-text-o' 
            when item_type = 'S' then 'fa-caret-square-o-right'
            when item_type = 'T' then 'fa-minus-square-o'

This changes the icon column from file URLs to icon class names. Click OK.

Next we have to set the icon type. Click Attributes under Task Tree then set Icon Type to fa. This specifies to use Font Awesome icons.

In the new Universal Theme the Font Awesome library is already part of the theme. This app is not using Universal Theme so we need to explicitly load the library.

In the rendering tree click the root page node. Then in the property editor under the CSS group File URLs property enter:


#IMAGE_PREFIX#libraries/font-awesome/4.2.0/css/font-awesome.min.css

You can remove this if you ever migrate to the Universal Theme.

Before trying this out lets think about what we just did compared to the old component view and edit pages. With component view I would have had to visit 3 different pages and apply changes on each. With Page Designer it is all done in one place. That saves time waiting for pages to load. The productivity gains increase the more edits you make.

Now press Save and Run. Notice that the icons are now shown. You can pick from any of the Font Awesome icons or with a bit more effort define your own CSS icons.

One style difference you may notice between this tree and the ones in Application Builder or a new Universal Theme app is that here the node label links are underlined. Currently there is a missing style to override the normal anchor style. You can correct this by adding the following CSS rule to the page Inline CSS.


.a-TreeView-label {
    text-decoration: none;
}

Click on the root page node in the Rendering tree. In the property editor under the CSS group enter the above rule in the Inline property. If you already have an application CSS file that is loaded on all pages you can add this rule there instead.

At this point we could be done but there is a better way to handle the Expand All and Collapse All buttons.

Step 3 Update the Expand and Collapse buttons

If you were to create a new tree region in a new app using the Application Builder wizards it would create buttons that use dynamic actions rather than putting javascript in URLs. JavaScript URLs are a bad thing and should be avoided. It would also make the buttons normal size rather than large.

Use Quick Edit and click on the Collapse All button. This brings us back to the Page Designer with the Collapse All button selected (the name is CONTRACT_ALL). Now in either the Grid Layout view or the Rendering Tree hold down the Ctrl key and click on the EXPAND_ALL button. Now both buttons are selected and we can use the property editor to change both components at once. This multi edit is another one of the productivity features of Page Designer.

In the property editor under Appearance change the Button Template from Large Button to Button. Under Behavior change the Action from Redirect to URL to Defined by Dynamic Action.

Now in the Rendering tree right click on the CONTRACT_ALL button and choose Create Dynamic Action. Change the Name property to collapse (the names are for your own understanding so you can pick any unique name you like). Then click on the Show node under the True folder. Change the Action to Collapse Tree. Change Selection Type to Region and then select the Task Tree region. That created a dynamic action so that when the Collapse All button is clicked the tree will collapse. Repeat these steps for the Expand All button except right click on EXPAND_ALL, set the Name to expand, the Action to Expand Tree.

Run the page and verify that the Expand All and Collapse All buttons still work. The old tree region has now been converted to the new APEX tree including new icons. It should look like this:

New Tree Final

You may notice that the jQuery Migrate plugin is still loaded on this page even though jsTree is no longer used. This is because of the global user interface setting Include jQuery Migrate, which is set to Yes when upgrading to APEX 5.0. More details here.

When you are sure that none of the components or custom JavaScript in your application require jQuery Migrate (or just to test) you can remove it. From the application home page click Edit Application Properties, click User Interface, click Edit Desktop. Change Include jQuery Migrate to No.

Summary

This shows how easy it is to migrate existing tree regions to the new APEX Tree for most cases. However if you have enhanced your old tree region with custom CSS style changes or called jsTree APIs then you will have more work to do. For CSS changes take a look at the new markup to see what classes it uses. The tree view widget API is undocumented and subject to change in ways that may not be backward compatible. But if you need to migrate your tree that used the jsTree API take a look at the code comments in libraries/apex/widget.treeView.js.

This also demonstrates productivity improvements in APEX 5.0 such as how the Page Designer and Developer Toolbar work together to make it very quick and efficient to edit APEX pages.

3 Comments

  1. John Snyders
    John Snyders Friday, June 26, 2015

    Good job finding the find method.
    The treeView widget does support async loading of child nodes. I’m working on a plugin/demo of this and more but I have no idea when it will be ready. You will need to create your own adapter and implement the fetchChildNodes method. You can also modify the adapter returned by $.apex.treeView.makeDefaultNodeAdapter. Look at the comments in the source.
    -John

  2. marco
    marco Friday, June 26, 2015

    Hi John,

    good post.
    I migrated the old jsTree to the new apex tree-region. I also implemented a little search-functionality with the public method find of the treeView. But I am not sure if it is possible to asynchronously load tree-nodes like it ist possible in the old jsTree. Do you have any experience with that issue?

Comments are closed.