Friday, November 12, 2010

Layout Tips - Organizing page content using <trh:tableLayout>

ADF Faces is packaged along with rich set of layout components which can be used to arrange other components on a page. Though these components are smart enough to meet most of your requirement, sometimes you may need to look around for other layout components to realize specific UI features. This discussion is based on such a scenario where I'm using <trh:tableLayout> for building certain part of the UI. btw, this post is in (logical) continuation of my previous post on Layout Tips - Stretching components....

In this post, I'm discussing a UI centric use case implementation using ADF Faces layout components along with MyFaces Trinidad <trh:tableLayout>. Though mixing of the components from these two families are not considered as good practice, sometimes you may need to move out of the box to make your application working :)

A Case Study

Requirement is to build a web page as shown in following screen shot.

In my experience, the painful phase of UI design is picking up the right layout component which works for a specific case. Let me share simple tip to make your life easier. To begin with, let us draw outlines over the screen elements as shown in the following diagram. You can follow this approach irrespective of the technology you are using for building the UI. I was using this approach for building Java Swing UI when I started my career ;)

Now the picture is more clear, the dark clouds are moving out and the silver lining is becoming visible :) The requirement here is that table component is expected to stretch to fit the available space in the browser window and the 'parameter form' displayed below should occupy fixed height and width. we may need to identify the right set of layout components to organize the page contents. One obvious candidate for top level container is panelStretchLayout component. This component stretches the child in the center facet to fill all of available space. So let us add table to center facet of the panelStretchLayout, and specify fixed height for bottom facet where the parameter from goes. The jsf page may look like as follows.

 <af:panelStretchLayout id="psl1" startWidth="50px"
  <f:facet name="center">
     <af:table value="#{bindings.EmployeesView1.collectionModel}"
  <f:facet name="bottom">
  <!--  parameter form goes here -->
  <f:facet name="center"/>
  <f:facet name="start"/>
  <f:facet name="end"/>
  <f:facet name="top"/>
Next step is to identify the layout for second part(parameter form) of the screen. Th challenge here is the uneven distribution of the UI elements across rows. Though panelFormLayout comes close to the requirement, unfortunately this doesn't give the desired out put. Time to look around for a smart component which acts more like wrapper over HTML <table> element. Search ends in Trinidad libraries where we can see our friend - <trh:tableLayout>. Please note that Trinidad components doesn't have any client peer components as we do have for ADF Faces. So you may need to be measured while choosing this guy.

Adding the Trinidad tag library

First step is to add the the required Trinidad tag libraries to your web project's class path. Select the web project, right click and select project properties. Using the Project properties window add the 'Trinidad Components' from the list.

Organizing the content using <trh:tableLayout>

<trh:tableLayout> is supposed to have <trh:rowLayout> for each row and <trh:rowLayout> in turn can take <trh:cellFormat> to hold the UI components. In this example, we may need to have 3 rows. Each <trh:rowLayout> can take different number of <trh:cellFormat> based on number of UI elements to be displayed in a row. Please note that you may need to keep label separate from the <af:inputText> for better result. To achieve this, set the attribute 'simple' as true for inputText component, and add a separate <af:outputLabel> for labeling each inputText field.

The last step in this exercise is to specify the columnSpan and rowSpan properties for <trh:cellFormat>. This decides whether cells can span across more than one column or row. This is an easy task if you have an 'overlay grid' drawn on top of the screen elements as we discussed at the beginning.

Finally, the high level mapping between the UI elements and layout components may look like as shown in the following diagram

You can download the sample workspace from here.
Please try running main.jspx to get a feel of the <trh:tableLayout> component.
[Runs with Oracle JDeveloper 11g R1 PS2 + HR Schema]

Learn More ...

There are a lot more points like this. If  you are curious to learn the internals of the ADF Business Components and ADF Binding Layer,  the following book is for you - Oracle ADF Real World Developer’s Guide.
More details about this book can be found in this post-


Spyros Doulgeridis said...

Very good post as usual! :) Although I had some problems in inheriting width of one type of components to the other.

Anonymous said...

Thanks a lot for your tuto it hepls me a lot !