« April 23, 2007 | Main | April 26, 2007 »

April 25, 2007 Archives

April 25, 2007

ADF Faces 10.1.3: Dynamic Menus w/ ADF Regions

While developing my application I reused a number of pages for different pages flows for different user roles. This resulted in the need for different sub menus (aka "menu2" facet in <af:panelPage>).

The Approach

Instead of putting the sub menu in every page, I've chosen to use <af:region> to reduce the code and be more flexible during the design. This region uses a member of the application's state bean. (An implementation detail of my application - see the SRDemo for a similar approach to store context information). The region itself retrieves the menu context and decides which menu to display.

Using a Region

Using a Region within a .jspx page is quite easy. Instead of your ADF Faces tags use the <af:region> tag to reference the specific region:

<f:facet name="menu2">
 <af:region id="menu2Region"
            regionType="demo.regions.menu2">
  <f:attribute name="create" value="false" />
 </af:region>
</f:facet>

Define a Region Mapping

To use a region we must tell ADF Faces where to find the definition of the region. This will be done in the WEB-INF/region-metadata.xml file.

<component>
 <component-type>demo.regions.menu2</component-type>
 <component-class>oracle.adf.view.faces.component.UIXRegion</component-class>
 <component-extension>
  <region-jsp-ui-def>/regions/subMenu.jspx</region-jsp-ui-def>
 </component-extension>
 <attribute>

  <attribute-name>create</attribute-name>
  <attribute-class>java.lang.String</attribute-class>
 </attribute>
</component>

This example also shows that a region can have parameters (or attributes) that are used within the region definition. You see the usage of parameters above.

Define a Region

Finally we define the region in a separate file which contains the complete tags we'd like to use.

<af:regionDef var="aParam"
 xmlns:f="http://java.sun.com/jsf/core"
 xmlns:af="http://xmlns.oracle.com/adf/faces">
 <!-- ... -->
</af:regionDef>

Don't forget to define the namespaces in the <af:regionDef> tag to make JDeveloper Code-Insight happy.

The Dynamic Region Content

Essentially, you put every tag you want to use within the <af:regionDef> tag. To add a bit dynamic for the context-based menu display, I've put the <af:switcher> around my different versions of the menus. Every possible case is wrapped by a normal JSF <f:facet> tag.

<af:switcher defaultFacet="default"
 facetName="#{userState.menuContext}">

 <f:facet name="organisation">
  <af:menuBar>
   <af:commandMenuItem
    text="#{res['page.organisation.create']}"
    action="createOrganisation"
    rendered="#{!userState.patientRole}"

    immediate="true"
    selected="#{aParam.create == 'true'}"/>
  </af:menuBar>
 </f:facet>
 <!-- more facets here -->
</af:regionDef>

Please note, how I determine the current menu context from the application context bean with facetName="#{userState.menuContext}".

We also see how the parameters are used. As these are Strings we have to compare them with literal values.

Setting the Menu Context

When I change the main menu context, an action is called and sets the current menu context field in the application context bean. Here is a sample of the action:

public String organisationAction() {
  setMenuContext("organisation");
  return "GlobalOrganisation";
}

Since the navigation  rule for the menus is designed as a global outcome ("GlobalOrganisation"), I've placed this action in the application context bean, too.

Conclusion

This sample is a fast, usable, and easy to understand solution (important for co-workers, or when I have to maintain it in two weeks time). There are more flexible solutions in ADF Faces available, but often much harder to read, maintain, etc.

About April 2007

This page contains all entries posted to Olaf Heimburger's Blog in April 2007. They are listed from oldest to newest.

April 23, 2007 is the previous archive.

April 26, 2007 is the next archive.

Many more can be found on the main index page or by looking through the archives.

Powered by
Movable Type and Oracle