This post describes how to implement an dvt:treemap
which shows a af:popup
when the user clicks on a detail node in the map.
The documentation of the dvt:treemap component tell us that the dvt:treemapnode supports the af:showPopupBehavior
tag and reacts on the ‘click’ and ‘mouseHover’ events.
This is part of the solution and allows us to begin implementing the use case. We add an af:showPopupBehavior
to the nodes we want to show detail information for.
After creating a default Fusion Web Application which uses the HR DB schema, we begin with creating the data model for the model project. For this small sample the departments and employees tables will be sufficient.
The views are named according to their usage to make it easier to understand the model. This is all we need for the model.
Let’s start with the UI which only consist of a single page. The page has a header part and a center part. In the center area we build the treemap by dragging the Departments from the data controls onto the page and dropping it as treemap. After that, in the dialog we specify the first level of the map to be the departmentId (which shows the department name as the label) and the for the second level we choose the employeeId (which shows the last name of the employee as label) from the employees. The whole process is shown in the gallery below.
The resulting treemap is very basic in it’s features, e.g. there is no legend as you see later.
In the next step we create an
af:popup
to show the nodes detail information. This process is outlined in the next gallery. We drag the popup component onto the page below the af:treemap
componentOne thing to take note of are the properties of the popup. First we set the content delivery to ‘lazyUncached’, which makes sure that the data is loaded every time the popup is opened. Otherwise we’ll see only the data from the first time the popup has been opened. Second change is to set the launcherVar to ‘source’. This is the variable name we later use to access the node data. Third change is to set the event context to ‘launcher’. This means that events delivered by the popup and its descendents are delivered in the context of the launch source.
The treemap for example, when an event is delivered ‘in context’ then the data for the node clicked is made ‘current’ before the event listener is called, so if getRowData()
is called on the collectionModel in the event listener it will return the data of the node that triggered the event. This is exactly what we need.
Finally we add a popupFetchListener to the popup which we use to get the data from the current node to a variable in the bindings. In the sample this variable ‘nodeInfo’ is defined in the variable iterator of the page and an attribute binding ‘nodeInfo1’ is added. More info on this can be found here.
The code below shows the popupFetchListener:
package de.hahn.blog.treemappopup.view.beans; import javax.el.ELContext; import javax.el.ExpressionFactory; import javax.faces.application.Application; import javax.faces.context.FacesContext; import oracle.adf.model.BindingContext; import oracle.adf.share.logging.ADFLogger; import oracle.adf.view.rich.event.PopupFetchEvent; import oracle.binding.AttributeBinding; import oracle.binding.BindingContainer; /** * Treemap handler bean * @author Timo Hahn */ public class TreemapBean { private static ADFLogger logger = ADFLogger.createADFLogger(TreemapBean.class); public TreemapBean() { } /** * listen to popup fetch. * @param popupFetchEvent event triggerd the fetch */ public void fetchListener(PopupFetchEvent popupFetchEvent) { // retrieve node information String lastName = (String) getValueFromExpression("#{source.currentRowData.lastName}"); Integer id = (Integer) getValueFromExpression("#{source.currentRowData.EmployeeId}"); //build info string String res = lastName + " id: " + id; logger.info("Information: " + res); // get the binding container BindingContainer bindings = BindingContext.getCurrent().getCurrentBindingsEntry(); // get an ADF attributevalue from the ADF page definitions AttributeBinding attr = (AttributeBinding) bindings.getControlBinding("nodeInfo1"); //set the value to it attr.setInputValue(res); } // get a value as object from an expression private Object getValueFromExpression(String name) { FacesContext facesCtx = FacesContext.getCurrentInstance(); Application app = facesCtx.getApplication(); ExpressionFactory elFactory = app.getExpressionFactory(); ELContext elContext = facesCtx.getELContext(); Object obj = elFactory.createValueExpression(elContext, name, Object.class).getValue(elContext); return obj; } }
Finally we have to design the popup to show the node info from the attribute binding ‘nodeInfo1’. The popup uses a dialog with an af:outputText
like
and set an
af:showPopupBehavior
to the node showing the employeesRunning the finished application brings up the treemap, not pretty but enough to see this use case working. If we click on an employee node we see the popup with the last name of the employee and the employee id, the primary key of the selected row in the employees iterator.
You can download the sample application which was build using JDeveloper 12.1.3 and the HR DB schema from GitHub.