The ICEfaces Tutorial
Table of Contents


Lesson: Using facelets dynamic includes

How to Use Facelets Dynamic Includes

Facelets is a view technology that focuses on building JSF component trees. Facelets includes many features such as:

We will use facelets to construct a navigation tree. This navigation tree will be built from a single ui:include tag. The nodes on the tree will link to various content pages.

This tutorial will discuss the following topics:

 

Configuring/Installing Facelets

The steps to get facelets up and running for your application is quite simple:

  1. Download the ICEfaces distribution and unzip it.
  2. Copy the icefaces-facelets.jar into your WEB-INF/lib directory.
  3. Add the Facelet init parameter to the web.xml file.
  4. Add the FaceletViewHandler to the faces-config.xml file.

The first two steps are fairly straight forward but the last two steps need to be described in detail.

Adding the init Parameter

The following code should be added to the web.xml file:

          ...
          <context-param>
            <param-name>javax.faces.DEFAULT_SUFFIX</param-name>
 	    <param-value>.jspx</param-value>
          </context-param>
          ...
      

This tells JSF to assume a prefix of jspx, which the Facelet's rendered can interpret. Facelets can use many other parameters depending on your application.

Adding the FaceletsViewHandler

For Facelets to work correctly, you'll need to tell JSF about the Facelets view handler. This is a plug-in that handles the Render Response and Restore View phases of the JSF request-processing life cycle. Add the following code to the faces-config.xml file:

          ...
          <application>
            <view-handler>
                com.icesoft.faces.facelets.D2DFaceletViewHandler
            </view-handler>
          </application>
          ...
      
 

Create the Web Pages

The beauty of dynamically including the of the web pages is that the majority of the jspx pages have very little code involved. First off the we'll look at the country-facelet.jspx code:

            ...
            <ui:composition template="mainTemplate.jspx">
                <ui:define name="faceletHeader">
                    <meta http-equiv="Content-Type"
                          content="text/html; charset=utf-8"></meta>
                    <title>
                        <ice:outputText value="Facelet Dynamic Include Tutorial"/>
                    </title>
                    <link href="./xmlhttp/css/xp/xp.css" rel="stylesheet" type="text/css"/>
                </ui:define>
            </ui:composition>
            ...
      

There are a few tags that may look unfamiliar and are described below:

For our example the composition tag included the mainTemplate.jsp page which will be described later. In the composition tag it also defines a 'faceletHeader', this will match a ui:include tag in the mainTemplate.jspx.

From this page it goes to the mainTemplate.jspx page. This page is a template for the entire application. It consists of a header, navigation bar, and a content section. The following is the code from the page:

            ...
            <head>
                <ui:insert name="faceletHeader">Headers </ui:insert>
            </head>
            <body>
                <table border="0" cellpadding="0"
                        cellspacing="0" width="100%">
                    <tr>
                        <td colspan="3">
                            <ui:insert name="header">
                                <h1>
                                    <ice:outputText value="ICEfaces Facelets Dynamic Include Tutorial"/>
                                </h1>
                                <ice:outputText>
                                    The following application uses a tree navigation menu 
                                    that is created using a dynamic ui:include tag.
                                </ice:outputText>
                                <hr/>
                            </ui:insert>
                        </td>
                    </tr>
                    <tr>
                        <td valign="top" width="150px" style="border-right:1px solid #999999;">
                            <ui:insert name="navigation">
                                <ui:include src="./navigation.jspx" />
                            </ui:insert>
                        </td>
                        <td valign="top" style="padding-left:10px;">
                            <ui:insert name="content">
                                <ui:include src="./content-facelet.jspx" />
                            </ui:insert>
                        </td>
                        <td></td>
                    </tr>
                </table> 
            </body>
            ...
      

At first it inserts the named content configured in the country-facelet page, this will include the title for the page. It then outlines the content of the page. Starting with a basic header that will remain the same no matter what content page is displayed. It then includes the navigation and content files into the template using the tag, ui:include. The Facelet tags used in this page is described below:

The mainTemplate page includes two pages, navigation.jspx and content-facelet.jspx. The navigation page is where the navigation tree is built dynamically. The content-facelet page is where the information is displayed.

As with the rest of the web pages the navigation.jspx code is fairly simple:

          ...          
            <ice:form
                xmlns:h="http://java.sun.com/jsf/html"
                xmlns:f="http://java.sun.com/jsf/core"
                xmlns:ice="http://www.icesoft.com/icefaces/component"
                id="navigationMenuForm">
                <div class="navTree">
                    <ice:tree
                        value="#{treeNavigation.model}"
                        var="item"
                        hideRootNode="false"
                        binding="#{treeNavigation.treeComponent}">
                        <ice:treeNode>
                            <f:facet name="content">
                                <ice:panelGroup style="display: inline">
                                    <ice:commandLink
                                        actionListener="#{item.userObject.contentVisibleAction}">
                                    <ice:outputText
                                        value="#{item.userObject.menuDisplayText}"/>
                                    </ice:commandLink>
                                </ice:panelGroup>
                            </f:facet>
                        </ice:treeNode>
                    </ice:tree>
                </div>
            </ice:form>
         ...
      

The page creates an ice:tree that is generated from a backing bean. The nodes are command links that function is defined in the backing bean.

The content-facelet page is also fairly simple:

          ...
            <ice:panelGroup>
                <h2>
                <ice:outputText
                    value="#{navigation.selectedPanel.menuContentTitle}"/>
                </h2>
                <div class="demoWindow">
                    <ui:include src="#{navigation.selectedPanel.menuContentInclusionFile}"/>
                </div>
                <br/>
            </ice:panelGroup>
          ...  
      

The page displays the contents title received from the backing bean and then displays the content that was defined by the backing bean.

 

Create the Backing Beans

In our example there are just three backing beans that are responsible for the creation and function of the navigation tree. The beans are:

The NavigationBean is fairly straight forward. It consists of a selectedPanel object and the getters and setter for this attribute. The class is used mainly by the page content bean to change the file that is being displayed in the application.

The PageContentBean is a little more complicated and is part of the major functionality for displaying content dynamically. The class extends the IceUserObject class, this class represents a DefaultMutableTreeNode as pert of the TreeModel. The class also holds some of the basic information regarding content such as:

The PageContentBean's methods consist of basic getters and setters and an action listener that will toggle the branch visibility.

The TreeNavigation is the bean that creates the tree model for navigation. Each node is a PageContentBean object. First off the root node is created in the constructor like this:

            ...
            // build root node so that children can be attached
            PageContentBean rootObject = new PageContentBean();
            rootObject.setMenuDisplayText("Country Fact Sheet");
            rootObject.setMenuContentTitle("Country Fact Sheet");
            rootObject.setMenuContentInclusionFile("./content/main.xhtml");
            rootObject.setTemplateName("mainPanel");
            rootObject.setNavigationSelection(navigationBean);
            rootObject.setPageContent(true);
            rootTreeNode = new DefaultMutableTreeNode(rootObject);
            rootObject.setWrapper(rootTreeNode);

            model = new DefaultTreeModel(rootTreeNode);
            ...
      

All the children will be attached to this node. The init method will create the rest of the tree. To create the children there are two differences. You can create a node that will be a parent of a branch or create a leaf that, when clicked, will display content. The following is an example on how to create a parent of a branch:

                ...
                // North America menu item
                branchObject = new PageContentBean();
                branchObject.setExpanded(false);
                branchObject.setMenuDisplayText("North America");
                branchObject.setMenuContentTitle("North America");
                branchObject.setTemplateName("northAmericaPanel");
                branchObject.setNavigationSelection(navigationBean);
                branchObject.setPageContent(false);
                DefaultMutableTreeNode branchNode = 
                        new DefaultMutableTreeNode(branchObject);
                branchObject.setWrapper(branchNode);
                // finally add the new custom component branch
                rootTreeNode.add(branchNode);
                ...
      

A new PageContentBean is created and its values are defined. Also the PageContentBean is wrapped in a DefaultMutableTreeNode which will make it compatible with the tree object. Once all vlaues have been set the node is added to the root.

The following is an example on how to add a leaf node under the parent branch:

                ...
                // North Ameica menu -> Canada
                branchObject = new PageContentBean();
                branchObject.setMenuDisplayText("Canada");
                branchObject.setMenuContentTitle("Canada Facts");
                branchObject.setMenuContentInclusionFile("./content/NA/canada.xhtml");
                branchObject.setTemplateName("canadaContentPanel");
                branchObject.setNavigationSelection(navigationBean);
                DefaultMutableTreeNode leafNode =
                        new DefaultMutableTreeNode(branchObject);
                branchObject.setWrapper(leafNode);
                branchObject.setLeaf(true);
                // finally add the new custom component branch
                branchNode.add(leafNode);
                ...
      

The creation of this bean is very similar to creating a parent object with a few differences. Instead of a branchNode being created a leafNode is created and added to the branchNode created in the parent, instead of the root node. Also the leaf attribute is set to true.

The basic structure is shown below:

Navigation Tree

Download the demo:

 

Examples that use Facelets Dynamic Includes

Example Source Notes
Component-Showcase-Facelets Available in release bundles The Component-Showcase-Facelets version (bundled in the ICEfaces release) uses dynamic includes for its navigation tree.
Dynamic-Include-Tutorial dynamic-include-tutorial source code Simple example demonstrating how to use Facelets dynamic includes.

The ICEfaces Tutorial
Table of Contents

Copyright 2006 ICEsoft Technologies Inc. All rights reserved.