Thursday, December 2, 2010

Happy Holidays everyone!

Wednesday, December 1, 2010

Creating a centered page layout using ADF Faces (only)

by Eduardo Rodrigues

It’s been a long time since I last posted here about my old friend: ADF. But now that I’m working in ADF BC’s awesome development team, I was already feeling the self-pressure and urge to go back to this vast subject. Let’s start easy though.

As you all might have noticed, ADF has gone a long way since it’s early days. ADF Faces 11g is quite different from its 10g predecessor. One of the differences, besides all the rich components and built-in AJAX capabilities, is the fact that some of the components that were present in 10g have moved from ADF Faces library to Apache Trinidad (or MyFaces). One of those components was the “rowLayout”. That layout component certainly makes it very easy to center its content in relation to the entire page, both horizontally and vertically. However, using Trinidad components ad tag libraries alongside with ADF Faces, although possible, may not be always desired. So, the question is: how to achieve same layout using only ADF Faces’ layout manager?

If you’re somewhat used to the particularities of ADF Faces’ layout manager, you probably already know that setting up a container that not only stretches 100% of the page’s (or of its parent container’s) height but also centers its content vertically is not as easy and straightforward as one would think.

Thinking fast, the first approach most come up with (including myself) is this:

panelStretchLayout (only center facet enabled) > panelGroupLayout (Layout = horizontal ; Valign = middle) > panelGroupLayout (Layout = vertical ; Halign = center)

Pretty intuitive and simple, right? Yes! But the layout manager doesn’t seem to agree.

The problem with this layout structure is basically the fact that a horizontal panelGroupLayout does not support being stretched inside a panelStretchLayout facet. This is actually clearly documented: http://goo.gl/GYVud

After a lot of trial-and-fail, I eventually found a way (thanks to my good friends and ADF gurus Maiko Rocha and George Maggessy).

The layout structure is this:

panelStretchLayout (top, bottom and center facets enabled; TopHeight = 33% ; BottomHeight = 33%) > panelGroupLayout (Layout = vertical ; Halign = center)

Even if you don’t need any content going in the Top or Bottom facets, it’s important to add at least an empty panelGroupLayout to both of them just to ensure the specified 33% of height will be allocated.

To wrap up, here’s a complete source code example of a page with a page-centered login form:


<?xml version='1.0' encoding='UTF-8'?>
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" version="2.1"
          xmlns:f="http://java.sun.com/jsf/core"
          xmlns:af="http://xmlns.oracle.com/adf/faces/rich">
  <jsp:directive.page contentType="text/html;charset=UTF-8"/>
  <f:view>
    <af:document id="d1" title="Login Page">
      <af:form id="f1" defaultCommand="#{'pgTplt:cbLogin'}">
            <af:panelStretchLayout id="psl1" startWidth="33%" endWidth="33%"
                                   topHeight="33%" bottomHeight="33%">
              <f:facet name="center">
                <af:panelGroupLayout id="pgl1" layout="vertical"
                                     halign="center">
                  <af:panelFormLayout id="pflLogin" rows="2" maxColumns="1">
                    <af:inputText id="itUsername" label="Username"
                                  value="#{Login.username}"/>
                    <af:inputText label="Password" id="itPassword" secret="true"
                                  value="#{Login.password}"/>
                    <af:spacer width="10" height="10" id="s1"/>
                    <af:commandButton text="Login" id="cbLogin"
                                      actionListener="#{Login.doLogin}"/>
                  </af:panelFormLayout>
                </af:panelGroupLayout>
              </f:facet>
              <f:facet name="bottom">
                <af:panelGroupLayout id="pgl2"/>
              </f:facet>
              <f:facet name="top">
                <af:panelGroupLayout id="pgl3"/>
              </f:facet>
            </af:panelStretchLayout>
      </af:form>
    </af:document>
  </f:view>
</jsp:root>

And this is how the page above should look like:


image