Servoy Tutorial: The Demise of the TreeView

Servoy Tutorial Photo Credit:
Gwen Vanhee via Compfight

This is a Servoy tutorial on using an alternative to the TreeView control in Servoy. This Servoy tutorial picks up where we left off in “Using CSS Components with Callbacks“. You should study that Servoy tutorial first, as this one will be a little more advanced.

Still with me? Okay, let’s kick it up a notch! You ever seen one of these? Well, as far as tree views go, this one looks pretty nice (if I do say so myself). The problem with tree views is, that users hate them. I have been involved in numerous large-scale commercial projects, and I can tell you that users despise the tree. In most cases, they find it hard to navigate and locate individual programs among all the nodes, expanding and collapsing nodes requires some precise mouse-control to click the little “+” or “-“, and they probably have just been over-used. Look, I don’t really know what the  problem is, I just know that the users groan when they see another tree being used for navigation.

TreeView_menu

So what is a developer to do? Do we have viable alternatives to the tree? Certainly we can’t use buttons to control all these programs; that would be a total mess. Even a menu would be hard to use because of all the parent groups used in this massive app. The bottom-line is we used the tree because its the best Servoy control to handle this much information in a compact space. Well, let’s think…who else is having problems like this, and solving them with elegant solutions. Ah, of course, the web developers! Why don’t we grab one of their components and hook it up to Servoy and see how it does? Absolutely! Let’s build this:

AccordianCSS_menu

This is a JQuery/CSS accordion menu control, and it’s pretty sweet! You can stylize the whole thing, changing the background color, highlight color, selected color, the font, font color, font size, everything; its all CSS. You click anywhere on a line and with a beautiful animated effect the group collapses or expands, hiding or revealing child nodes. Icons can be assigned to every row and the hover highlight color (light blue shown here) follows your mouse as you move over the nodes. It even has a collapse all / expand all feature that I put at the bottom. Well this rocks, it’s running in Servoy, and I’m going to show you how to do it!

Were going to start with three variables that we are going to add to scopes.api that I create in my modBase. We will talk about encapsulation some other time, but basically, I use scopes to organize my information into neat namespaces. My modBase is accessible to all my other modules in a large application, and is typically where all my relations, media, and scopes (like scopes.api, scopes.events, scopes.utils, etc.)  are maintained.

In scopes.api, I also include a start-up script that is run when my application launches. It’s purpose is to prepare the application by restoring user preferences, initializing things, etc. In this case, I am going to load the css style sheet for the control, the font-awesome style sheet (icons), and the jQuery.js file for the accordion control. I use the WebClientUtils plugin to do load my css and js files at start-up,  which allows me to use the control on any form, and not have to worry about initializing them. Load it once and use them anywhere.

The other thing I will do in the start-up function is to build my “html_eventCallBack” handler’s HTML. This HTML includes the WebClientUtils plugin to capture a “fireEvent” callback and call my main “scopes.events.eventHandler”, passing it some parameters. What this allows me to do is place a non-editable HTML area on any form, use “scopes.api.html_eventCallBack” as the dataprovider, and I can capture any callback event from any CSS control on that form. Effectively, I am using the same event handler on all my forms to capture all my callbacks from all my controls. The two parameters it expects are the “eventName” ,which will be unique for each event fired from a control, and an “eventMsg” type, like “Nav”, which tells the event handler what type of event is being received, so it can be properly routed from one central location.

In my modBase scopes.events, I create my central event handler method. This is the method that will receive all the events fired from controls in use on forms, and route the requests to the appropriate functions by “eventMsg” type. In this example, we are only going to handle “Nav” types, and I will use a single “notImplementedYet” function for all events (just to keep it simple).
The event handler will check modBase scopes.enums for the routing details to determine which method to call for a given event. All my events call the “notImplementedYet” function, but you would call specific public methods in a real-world scenario. Enums, in case you do not know, are nothing more than a list of constants consisting of name/value pairs. They are a great way to keep these organized, and can be used in relations. Here is my scopes.enums.NAV:
The next step is to work on the form where we are going to use the accordion control. Here I will place a non-editable HTML area on the form and use scopes.api.html_accordian as the dataprovider. I then create an onLoad() method and add the code that will load scopes.api.html_accordian on form load.
Now, I should mention a couple of things here.

  • You don’t have to wrap each HTML line in quotes like I do here, building up one big HTML string. You can instead create an XML object (wrap the whole thing in brackets) and use .toXMString() to convert it into a string.
  • If you have functions that contain invalid characters for XML, then you can wrap those using the CDATA tag. You would then have to remove the tags using something like:
  • There is another way to interact with the browser environment without using the WebClientUtils plugin, which uses a hidden button in the body of the HTML to call a global method. I personally never use this approach and find the WebClientUtils plugin easier to work with.
  • I use a specific workflow for creating the HTML for the form.
    • The css control comes with sample HTML. I grab that and paste it into WebStorm. I will now edit the HTML adding my id for the event name, the onclick events, obviously my data, images, etc.
    • Once I am satisfied with the HTML, I then copy it from WebStorm and paste it into a simple Servoy HTML converter that will wrap it all in quotes for me. Here is the method I use on a form which has two text areas with form variables, _in and _out, as dataproviders.

      html_converter

The last thing that I add to the onLoad() method of my form is the code to load “scopes.api.html_collapseAll” with some jQuery/HTML code. This is the dataprovider for a non-editable HTML area that I place on the form immediately below the accordion’s HTML area.

I also place onto the form a non-editable HTML area that has “scopes.api.html_eventCallBack” as the dataprovider. Here I show it with a purple background so you can see it is there. In a real use case scenario, this HTML area is hidden, will capture the callbacks fired from the control, and route them to my event handler in scopes.events. Make sense?

eventHandler

So, that’s it for this Servoy tutorial. We now have an accordion control that replaces our tree, which will fire events when we interact with it. The events are handled by the event handler in scopes.events, and routed to the appropriate function using the enum mapping we setup. Everything is easy to maintain from centralized areas, and we have built it so we can easily capture events from other controls, on other forms, as well. We can expand the event handler to process any type of event, building out new enum maps as required.

I hope that this Servoy tutorial helps you further understand how to use CSS controls in Servoy, and how to organize your code so it will be easy to maintain and expand, as you add more and more controls, and need to handle more and more events.

That concludes this Servoy tutorial. I hope you enjoyed it!

Gary Dotzlaw
Gary Dotzlaw has 20+ years of experience as a professional software developer and has worked with over 100 companies throughout the USA and Canada. Gary has extensive qualifications in all facets of the project life cycle, including initial feasibility analysis, conceptual design, technical design, development, implementation and deployment. Gary is an expert Servoy Developer, with extensive large-commercial project experience, and has written numerous advanced tutorials on Servoy development.