Skip Headers
Oracle® Fusion Middleware Web User Interface Developer's Guide for Oracle Application Development Framework
11g Release 1 (11.1.1.4.0)

Part Number B31973-08
Go to Documentation Home
Home
Go to Book List
Book List
Go to Table of Contents
Contents
Go to Index
Index
Go to Master Index
Master Index
Go to Feedback page
Contact Us

Go to previous page
Previous
Go to next page
Next
View PDF

8 Organizing Content on Web Pages

This chapter describes how to use several of the ADF Faces layout components to organize content on web pages.

This chapter includes the following sections:

8.1 Introduction to Organizing Content on Web Pages

ADF Faces provides a number of layout components that can be used to arrange other components on a page. Usually, you begin building your page with these components. You then add components that provide other functionality (for example rendering data or rendering buttons) either inside facets or as child components to these layout components.

Tip:

You can create page templates that allow you to design the layout of pages in your application. The templates can then be used by all pages in your application. For more information, see Chapter 19, "Creating and Reusing Fragments, Page Templates, and Components."

In addition to layout components that simply act as containers, ADF Faces also provides interactive layout components that can display or hide their content, or that provide sections, lists, or empty space. Some layout components also provide geometry management functionality, such as stretching their contents to fit the browser windows as the window is resized, or the capability to be stretched when placed inside a component that stretches. For more information about stretching and other geometry management functionality of layout components, see Section 8.2.1, "Geometry Management and Component Stretching."

Table 8-1 briefly describes each of the ADF Faces layout components.

Table 8-1 ADF Faces Layout Components

Component Description Can Stretch Children Can Be Stretched

Page Management Components

   
 

document

Creates each of the standard root elements of an HTML page: <html>, <body>, and <head>. All pages must contain this component. For more information, see Section 8.2, "Starting to Lay Out a Page."

X

 
 

form

Creates an HTML <form> element. For more information, see Section 8.2, "Starting to Lay Out a Page."

   

Page Layout Containers

   
 

panelStretchLayout

Contains top, bottom, start, center, and end facets where you can place other components. For more information, see Section 8.3, "Arranging Contents to Stretch Across a Page."

X

X (when the dimensionsFrom attribute is set to parent)

 

panelSplitter

Divides a region into two parts (first facet and second facet) with a repositionable divider between the two. You can place other components within the facets. For more information, see Section 8.4, "Using Splitters to Create Resizable Panes."

X

X (when the dimensionsFrom attribute is set to parent)

 

panelDashboard

Provides a columnar display of child components (usually panelBox components). For more information, see Section 8.7, "Arranging Contents in a Dashboard."

X

X (when the dimensionsFrom attribute is set to parent)

 

panelBorderLayout

Can have child components, which are placed in its center, and also contains 12 facets along the border where additional components can be placed. These will surround the center. For more information, see Section 8.5, "Arranging Page Contents in Predefined Fixed Areas."

   
 

panelFormLayout

Positions input form controls, such as inputText components so that their labels and fields line up vertically. It supports multiple columns, and contains a footer facet. For more information, see Section 8.6, "Arranging Content in Forms."

   

Components with Show/Hide Capabilities

   
 

showDetailHeader

Can hide or display contents below the header. Often used as a child to the panelHeader component. For more information, see Section 8.8, "Displaying and Hiding Contents Dynamically."

X (if the type attribute is set to stretch)

X (if the type attribute is set to stretch)

 

showDetailItem

Used to hold the content for the different panes of the panelAccordion or different tabs of the panelTabbed component. For more information, see Section 8.9, "Displaying or Hiding Contents in Accordion Panels and Tabbed Panels."

X (if it contains a single child component)

 
 

panelBox

Titled box that can contain child components. Has a toolbar facet. For more information, see Section 8.8, "Displaying and Hiding Contents Dynamically."

 

X

 

panelAccordion

Used in conjunction with showDetailItem components to display as a panel that can be expanded or collapsed. For more information, see Section 8.9, "Displaying or Hiding Contents in Accordion Panels and Tabbed Panels."

 

X (when the dimensionsFrom attribute is set to parent)

 

panelTabbed

Used in conjunction with showDetailItem components to display as a set of tabbed panels. For more information, see Section 8.9, "Displaying or Hiding Contents in Accordion Panels and Tabbed Panels."

If you want the tabs to be used in conjunction with navigational hierarchy, for example each tab is a different page or region that contains another set of navigation items, you may instead want to use a navigationPane component in a navigational menu. For more information, see Section 18.5, "Using Navigation Items for a Page Hierarchy."

 

X (when the dimensionsFrom attribute is set to parent)

 

showDetail

Hides or displays content through a toggle icon. For more information, see Section 8.8, "Displaying and Hiding Contents Dynamically."

   

Miscellaneous Containers

   
 

panelHeader

Contains child components and provides a header that can include messages, toolbars, and help topics. For more information, see Section 8.10, "Displaying Items in a Static Box."

X (if the type attribute is set to stretch)

X (if the type attribute is set to stretch)

 

panelCollection

Used in conjunction with collection components such as table, tree and treeTable to provide menus, toolbars, and status bars for those components. For more information, see Section 10.8, "Displaying Table Menus, Toolbars, and Status Bars."

X (only a single table, tree, or tree table)

X

 

decorativeBox

Creates a container component whose facets use style themes to apply a bordered look to its children. This component typically acts as a look and feel transition between areas on a page. For example, a page that has a dark background for its template can use the decorative box to transition to a white background for its main area. For more information, see Section 8.10, "Displaying Items in a Static Box."

X (in the Center facet)

X (when the dimensionsFrom attribute is set to parent)

 

inlineFrame

Creates an inline iframe tag.

 

X

 

navigationPane

Creates a series of navigation items representing one level in a navigation hierarchy. For more information, see Section 18.5, "Using Navigation Items for a Page Hierarchy."

 

X (if configured to display tabs)

 

panelList

Renders each child component as a list item and renders a bullet next to it. Can be nested to create hierarchical lists. For more information, see Section 8.11, "Displaying a Bulleted List in One or More Columns."

   
 

panelWindow

Displays child components inside a popup window. For more information, see Section 13.2, "Declaratively Creating Popup Elements."

   
 

toolbox

Displays child toolbar and menu components together. For more information, see Section 14.3, "Using Toolbars."

   

Grouping Containers

   
 

panelGroupLayout

Groups child components either vertically or horizontally. Used in facets when more than one component is to be contained in a facet. For more information, see Section 8.12, "Grouping Related Items."

 

X (only if set to scroll or vertical layout)

 

group

Groups child components without regard to layout unless handled by the parent component of the group. Used in facets when more than one component is to be contained in a facet. For more information, see Section 8.12, "Grouping Related Items."

   

Spacing Components

   
 

separator

Creates a horizontal line between items. For more information, see Section 8.13, "Separating Content Using Blank Space or Lines."

   
 

spacer

Creates an area of blank space. For more information, see Section 8.13, "Separating Content Using Blank Space or Lines."

   

8.2 Starting to Lay Out a Page

JSF pages that use ADF Faces components must have the document tag enclosed within a view tag. All other components that make up the page then go in between <af:document> and </af:document>. The document tag is responsible for rendering the browser title text, as well as the invisible page infrastructure that allows other components in the page to be displayed. For example, at runtime, the document tag creates the root elements for the client page. In HTML output, the standard root elements of an HTML page, namely, <html>, <head>, and <body>, are generated.

By default, the document tag is configured to allow capable components to stretch to fill available browser space. You can further configure the tag to allow a specific component to have focus when the page is rendered, or to provide messages for failed connections or warnings about navigating before data is submitted. For more information, see Section 8.2.5, "How to Configure the document Tag."

Typically, the next component used is the ADF Faces form component. This component creates an HTML form element that can contain controls that allow a user to interact with the data on the page.

Note:

Even though you can have multiple HTML forms on a page, you should have only a single ADF Faces form tag per page. For more information, see Section 8.6, "Arranging Content in Forms."

JDeveloper automatically inserts the view, document, and form tags for you, as shown in Example 8-1. For more information, see Section 2.4, "Creating a View Page."

Example 8-1 Initial JSF Page Created by JDeveloper Wizard

<?xml version='1.0' encoding='UTF-8'?>
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" version="2.0"
          xmlns:f="http://java.sun.com/jsf/core"
          xmlns:h="http://java.sun.com/jsf/html"
          xmlns:af="http://xmlns.oracle.com/adf/faces/rich">
  <jsp:directive.page contentType="text/html;charset=UTF-8"/>
  <f:view>
    <af:document>
      <af:form/>
    </af:document>
  </f:view>
</jsp:root>

Once those tags are placed in the page, you can use the layout components to control how and where other components on the page will render. The component that will hold all other components is considered the root component. Which component you choose to use as the root component depends on whether you want the contained components to display their contents so that they stretch to fit the browser window, or whether you want the contents to flow, using a scrollbar to access any content that may not fit in the window. For more information about stretching and flowing, see Chapter 8, "Geometry Management and Component Stretching."

Tip:

Instead of creating your layout yourself, you can use JDeveloper's quick layout templates, which provide correctly configured components that will display your page with the layout you want. For more information, see Section 8.2.3, "Using Quick Start Layouts."

8.2.1 Geometry Management and Component Stretching

Geometry management is the process by which the user, parent components, and child components negotiate the actual sizes and locations of the components in an application. At the heart of the RCF geometry management solution is a resize notification mechanism that allows components that support geometry management to be notified of browser resize activity. The following scenarios trigger the notification:

  • Load: When the page contents are first loaded, allowing initial sizing to take place.

  • Browser resize: When the browser window is resized.

  • Partial replacement: When a portion of the page is updated through partial page rendering, any newly inserted components are notified, allowing them to perform any necessary geometry management.

  • Visibility change: When a component that was initially configured to be invisible is made visible (components that are initially not visible do not receive notification).

  • Explicit resize: When components that allow themselves to be resized (for example the panelSplitter), are resized by the user.

By default, the root component will stretch automatically to consume the browser's viewable area, provided that component supports geometry management and therefore can stretch its child components. Examples of geometry management components are panelStretchLayout and panelSplitter.

Note:

The framework does not consider popup dialogs, popup windows, or non-inline messages as root components. If a form component is the direct child component of the document component, the framework will look inside the form tag for the visual root. For information on sizing a popup, see Chapter 13, "Using Popup Dialogs, Menus, and Windows."

When the user resizes the browser window, and when there is a single maximized root visual component inside of the document component, that visual root component will also resize along with the browser window. If the root component supports stretching its child components (and they in turn support being stretched), the size of the child components will also recompute, and so on down the component hierarchy until a flowing layout area is reached; that is, an area that does not support stretching of its child components. You do not have to write any code to enable the stretching.

As shown in Table 8-1, the panelStretchLayout, panelSplitter, and panelDashboard components are components that can be stretched and can also stretch their child components. Additionally, when the showDetailItem component is used as a direct child of the panelAccordion or panelTabbed component, the contents in the showDetailItem component can be stretched. Therefore, the panelStretchLayout, panelSplitter, panelDashboard, panelAccordion with a showDetailItem component, and a panelTabbed with a showDetailItem component, are the components you should use as root components when you want to make the contents of the page fill the browser window.

For example, Figure 8-1 shows a table placed in the center facet of the panelStretchLayout component. The table stretches to fill the browser space. When the entire table does not fit in the browser window, scrollbars are added in the data body section of the table.

Figure 8-1 Table Inside a Component That Stretches Child Components

Table is stretched

Figure 8-2 shows the same table, but nested inside a panelGroupLayout component, which cannot stretch its child components (for clarity, a dotted red outline has been placed around the panelGroupLayout component). The table component displays only a certain number of columns and rows, determined by properties on the table.

Figure 8-2 Table Inside a Component That Does Not Stretch Its Child Components

Table is not stretched

Performance Tip:

The cost of geometry management is directly related to the complexity of child components. Therefore, try minimizing the number of child components that are under a parent geometry-managed component.

8.2.2 Nesting Components Inside Components That Allow Stretching

Even though you choose a component that can stretch its child components, only the following components will actually stretch:

  • inputText (when configured to stretch)

  • decorativeBox (when configured to stretch)

  • panelAccordion (when configured to stretch)

  • panelBox

  • panelCollection

  • panelDashboard (when configured to stretch)

  • panelGroupLayout (with the layout attribute set to scroll or vertical)

  • panelSplitter (when configured to stretch)

  • panelStretchLayout (when configured to stretch)

  • panelTabbed (when configured to stretch)

  • region

  • table (when configured to stretch)

  • tree (when configured to stretch)

  • treeTable (when configured to stretch)

The following layout components cannot be stretched when placed inside a facet of a component that stretches its child components:

  • panelBorderLayout

  • panelFormLayout

  • panelGroupLayout (with the layout attribute set to default or horizontal)

  • panelHeader

  • panelLabelAndMessage

  • panelList

  • showDetail

  • showDetailHeader

  • tableLayout (MyFaces Trinidad component)

Because these components cannot be stretched, you cannot place them in a facet of any component that stretches its child components. So if you want to use one of these components within the facet of component that does stretch its child components, you must wrap it in a component that can be stretched, but one that does not stretch its child components. If you do not, you may see unexpected results when the component renders.

For example, suppose you have a panelStretchLayout as the first component on your page. You then add a panelSplitter component that is configured to be stretched. Now to the first facet of the panelSplitter component, say you add a panelGroupLayout component with its layout attribute set to scroll (which means it can stretch), and inside that, you add a panelCollection component, and then finally a table component.

To the second facet of the panelSplitter, suppose you add just the panelCollection and table components, as shown in Figure 8-3. Components that can stretch their children are green and components that can be stretched (but cannot stretch their children) are blue.

Figure 8-3 Layout Using Geometry-Managed Components

Layout Using Geometry Managing Components

As shown in Figure 8-4, when the page is run, the panelCollection and table components in the panelGroupLayout do not stretch, while the ones directly in the panelSplitter component do stretch.

Figure 8-4 Geometry-Managed Components Affect the Layout of the Page

Table on left does not stretch

Because the panelStretchLayout component can stretch its child components, and because the panelSplitter component was configured to stretch, both stretch to fill up available browser space. Because panelSplitter component can stretch its child components and because on the left, panelGroupLayout component with its layout attribute set to scroll can be stretched, and on the right, the panelCollection component can be stretched, both of those stretch to fill up available browser space. However, the panelGroupLayout component cannot stretch its child components, while the panelCollection component can stretch a single table. Therefore, the panelCollection component on the left does not stretch, even though its parent does.

Tip:

Do not attempt to stretch any of the components in the list of components that cannot stretch by setting their width to 100%. You may get unexpected results. Instead, surround the component to be stretched with a component that can be stretched. For components that can be stretched, see Table 8-1.

Now suppose on the left, instead of a table component, you want to add a panelList component. You would not need the panelCollection component (as that is used only for tables), so you might also think you would not need to use the panelGroupLayout component to group the panelList component with another component. However, because the panelList component would then be a direct child of the panelSplitter component, and because the panelSplitter component stretches its child components and the panelList component cannot be stretched, you would need to keep the panelGroupLayout (set to scroll) and place the panelList component as a child to the panelGroupLayout component.

This way, the panelSplitter component can stretch the panelGroupLayout component, but the panelGroupLayout component will not try to stretch the panelList component. Because the panelGroupLayout component can be stretched, but does not stretch its child components, it allows the transition between a layout that stretches and one that flows.

Components that can be stretched but do not stretch their children are considered transition components. Transition components must always be used between a component that stretches its children and a component that does not stretch.

8.2.3 Using Quick Start Layouts

When you use the New Gallery Wizard to create a JSF JSP page (or a page fragment), you can choose from a variety of predefined quick start layouts. When you choose one of these layouts, JDeveloper adds the necessary components and sets their attributes to achieve the look and behavior you want. You can choose from one-, two-, and three-column formats. Within those formats, you can choose how many separate panes will be displayed in each column, and if those panes can stretch or remain a fixed size. Figure 8-5 shows the different layouts available in the two-column format.

Figure 8-5 Quick Layouts

You can choose from different layouts.

Along with adding layout components, you can also choose to apply a theme to the chosen quick layout. These themes add color styling to some of the components used in the quick start layout. To see the color and where it is added, see Appendix D, "Quick Start Layout Themes." For more information about themes, see Section 20.3.4, "How to Apply Themes to Components."

In addition to saving time, when you use the quick layouts, you can be sure that layout components are used together correctly to achieve the desired outcome. For more information about creating pages using the quick layouts, see Section 2.4, "Creating a View Page."

8.2.4 Tips for Using Geometry-Managed Components

To ensure your page is displayed as expected in all browsers, use one of the quick layouts provided by JDeveloper when you create a page. These ensure that the correct components are used and configured properly. For more information, see Section 8.2.3, "Using Quick Start Layouts."

Best Practice:

Use quick start layouts to avoid layout display issues.

However, if you wish to create your layout yourself, follow these tips for creating a layout that includes both stretched and flowing components:

  • Place the page contents inside a root component that performs geometry management, either panelStretchLayout, panelSplitter, panelAccordion with a showDetailItem, or panelTabbed with a showDetailItem.

  • Never specify a height value with percent units. Instead, build a component structure out of components that support being stretched and that stretch their child components.

  • Inside this stretchable structure, create islands of nonstretched or flowing components by using transition components, such as the panelGroupLayout component with the layout attribute set to scroll. This component will provide the transition between stretched and flowing components because it supports being stretched but will not stretch its child components.

  • Never try to stretch something vertically inside a nonstretched or flowing container because it will not act consistently across web browsers.

  • For components contained in a parent flowing component (that is, a component that does not stretch its children), do not set widths greater than 95%. If you do, you may get unexpected results.

    • If the parent component is 768 pixels or greater, set the styleClass attribute on the component to be stretched to AFStretchWidth. This style will stretch the component to what appears to be 100% of the parent container, taking into account different browsers and any padding or borders on the parent.

    • If the parent component is 768 pixels or less, set the styleClass attribute on the component to be stretched to AFAuxiliaryStretchWidth. This style will stretch the component to what appears to be 100% of the parent container, taking into account different browsers and any padding or borders on the parent.

      Note:

      The two different styles are needed due to how Microsoft Internet Explorer 7 computes widths inside scrolling containers (this has been resolved in Internet Explorer 8). Unless you can control the version of browser used to access your application, you should use these styles as described.
  • Never use the position style.

  • Ensure that the maximized attribute on the document tag is set to true (this is the default). For more information about setting the attribute, see Section 8.2.5, "How to Configure the document Tag."

The remainder of this chapter describes the ADF Faces layout components and how they can be used to design a page. You can find information about how each component handles stretching in the respective "What You May Need to Know About Geometry Management" sections.

8.2.5 How to Configure the document Tag

The document tag contains a number of attributes that you can configure to control behavior for the page. For example, you can configure the tag so that one component has focus when the page is first rendered. You can also configure the tag to display a warning message if a user attempts to navigate off the page and the data has not been submitted. You can also set the document to use a different state saving method than the rest of the application.

To configure the document tag:

  1. In the Structure window, select the af:document node.

  2. In the Property Inspector, expand the Common section and set the following:

    • InitialFocusId: Use the dropdown menu to choose Edit. In the Edit Property dialog, select the component that should have focus when the page first renders.

      Because this focus happens on the client, the component you select must have a corresponding client component. For more information, see Section 3.4, "Instantiating Client-Side Components."

    • Maximized: Set to true if you want the root component to expand to fit all available browser space. When the document tag's maximized attribute is set to true, the framework searches for a single visual root component, and stretches that component to consume the browser's viewable area, provided that the component can be stretched. Examples of components that support this are panelStretchLayout and panelSplitter. The document tag's maximized attribute is set to true by default. For more information, see Section 8.2.1, "Geometry Management and Component Stretching."

    • Title: Enter the text that should be displayed in the title bar of the browser.

  3. Expand the Appearance section and for the FailedConnectionText attribute, enter the text you want to be displayed if a connection cannot be made to the server.

  4. Expand the Other section and set the following:

    • UncommitedDataWarning: Set to on if you want a warning message displayed to the user when the application detects that data has not been committed. This can happen because either the user attempts to leave the page without committing data or there is uncommitted data on the server. By default, this is set to off.

    • StateSaving: Set to the type of state saving you want to use for a page.

      For ADF Faces applications, it is recommended to have the application use client state saving with tokens, which saves page state to the session and persists a token to the client. This setting affects the application globally, such that all pages have state saved to the session and persist tokens with information regarding state.

      However, there may be a page for which you which you want the state saved differently. For example, when a user posts back to a login page after an extended period of time, you do not want the session time out error to be displayed. By changing the stateSaving attribute on the page to client, then when the user posts back to the login page, the time out error will not display.

      You can override the global setting in web.xml to one of the following for the page:

      • client: The state is saved fully to the client, without the use of tokens. This setting keeps the session expired messages from being displayed.

      • default: The state of the page is based on whatever is set in web.xml.

      • server: The state of the page is saved on the server.

      For more information about state saving, see Appendix A, "Configuration in web.xml."

8.3 Arranging Contents to Stretch Across a Page

Use the panelStretchLayout component to arrange content in defined areas on a page and when you want the content to be able to stretch when the browser is resized. The panelStretchLayout component is one of the components that can stretch components placed in its facets. Figure 8-6 shows the component's facets.

Figure 8-6 Facets in the panelStretchLayout Component

Components can be placed in facets

Note:

Figure 8-6 shows the facets when the language reading direction of the application is configured to be left-to-right. If instead the language direction is right-to-left, the start and end facets are switched.

When you set the height of the top and bottom facets, any contained components are stretched up to fit the height. Similarly, when you set the width of the start and end facets, any components contained in those facets are stretched to that width. If no components are placed in the facets, then that facet does not render. That is, that facet will not take up any space. If you want that facet to take up the set space but remain blank, insert a spacer component. See Section 8.13, "Separating Content Using Blank Space or Lines." Child Components components in the center facet are then stretched to fill up any remaining space. For more information about component stretching, see Section 8.2.1, "Geometry Management and Component Stretching."

Instead of setting the height of the top or bottom facet, or width of the start or end facet to a dimension, you can set the height or width to auto. This allows the facet to size itself to use exactly the space required by the child components of the facet. Space will be allocated based on what the web browser determines is the required amount of space to display the facet content.

Performance Tip:

Using auto as a value will degrade performance of your page. You should first attempt to set a height or width and use the auto attribute sparingly.

The File Explorer application uses a panelStretchLayout component as the root component in the template. Child components are placed only in the center and bottom facets. Therefore, whatever is in the center facet stretches the full width of the window, and from the top of the window to the top of the bottom facet, whose height is determined by the bottomHeight attribute. Example 8-2 shows abbreviated code from the fileExplorerTemplate file.

Example 8-2 panelStretchLayout in the File Explorer's Template File

<af:panelStretchLayout
    bottomHeight="#{attrs.footerGlobalSize}">
  <f:facet name="center">
    <af:panelSplitter orientation="vertical" ...>
.
.
.
    </af:panelSplitter
  </f:facet>
  <f:facet name="bottom">
    <af:panelGroupLayout layout="vertical">
. 
.
.
    </af:panelGroupLayout>
  </f:facet>
</af:panelStretchLayout>    

The template uses an EL expression to determine the value of the bottomHeight attribute. This expression resolves to the value of the footerGlobalSize attribute defined in the template, which by default is 0. Any page that uses the template can override this value. For example, the index.jspx page uses this template and sets the value to 30. Therefore, when the File Explorer application renders, the contents in the panelStretchLayout component begin 30 pixels from the bottom of the page.

8.3.1 How to Use the panelStretchLayout Component

The panelStretchLayout component cannot have any direct child components. Instead, you place components within its facets. The panelStretchLayout is one of the components that can be configured to stretch any components in its facets to fit the browser. You can nest panelStretchLayout components. For more information, see Section 8.2.2, "Nesting Components Inside Components That Allow Stretching."

To create and use the panelStretchLayout component:

  1. In the Component Palette, from the Layout panel, drag and drop a Panel Stretch Layout to the JSF page.

  2. In the Property Inspector, expand the Common section and set the attributes as needed.

    When there are child components in the top, bottom, start, and end facets, these components occupy space that is defined by the topHeight, bottomHeight, startWidth, and endWidth attributes. For example, topHeight attribute specifies the height of the top facet, and startWidth attribute specifies the width of the start facet. Child components in top and bottom facets are stretched up to the height set by topHeight and bottomHeight attributes, respectively, and child components in start and end facets are stretched up to the width set by startWidth and endWidth attributes, respectively. Instead of setting a numeric dimension, you can set the topHeight, bottomHeight, startWidth and endWidth attributes to auto and the browser will determine the amount of space required to display the content in the facets.

    Note:

    If you set a facet to use auto as a value for the width or height of that facet, the child component does not have to be able to stretch. In fact, it must use a stable, standalone width that is not dependent upon the width of the facet.

    For example, you should not use auto on a facet whose child component can stretch their children automatically. These components have their own built-in stretched widths by default which will then cause them to report an unstable offsetWidth value, which is used by the browser to determine the amount of space.

    Additionally, you should not use auto in conjunction with a child component that uses a percentage length for its width. The facet content cannot rely on percentage widths or be any component that would naturally consume the entire width of its surrounding container.

    If you do not explicitly specify a value, by default, the value for the topHeight, bottomHeight, startWidth, and endWidth attributes is 50 pixels each. The widths of the top and bottom facets, and the heights of the start and end facets are derived from the width and height of the parent component of panelStretchLayout.

    Tip:

    If a facet does not contain a child component, it is not rendered and therefore does not take up any space. You must place a child component into a facet in order for that facet to occupy the configured space.
  3. By default, the panelStretchLayout component stretches to fill available browser space. If you want to place the panelStretchLayout component inside a component that does not stretch its children, then you need to configure the panelStretchLayout component to not stretch.

    You configure whether the component will stretch or not using the dimensionsFrom attribute. To do so, expand the Other section, and set DimensionsFrom to one of the following:

    • children: Instead of stretching, the panelStretchLayout component will get its dimensions from its child component.

      Note:

      If you use this setting, you cannot use a percentage to set the height of the top and bottom facets. If you do, those facets will try to get their dimensions from the size of this panelStretchLayout component, which will not be possible, as the panelStretchLayout component will be getting its height from its contents, resulting in a circular dependency If a percentage is used for either facet, it will be disregarded and the default 50px will be used instead.

      Additionally, you cannot set the height of the panelStretchLayout component (for example through the inlineStyle or styleClass attributes) if you use this setting. Doing so would cause conflict between the panelStretchLayout height and the child component height.

    • parent: the size of the panelStretchLayout component will be determined in the following order:

      • From the inlineStyle attribute.

      • If no value exists for inlineStyle, then the size is determined by the parent container (that is, the panelStretchLayout component will stretch).

      • If the parent container is not configured or not able to stretch its children, the size will be determined by the skin.

    • auto: If the parent component to the panelStretchLayout component allows stretching of its child, then the panelStretchLayout component will stretch to fill the parent. If the parent does not stretch its children then the size of the panelStretchLayout component will be based on the size of its child component.

  4. To place content in the component, drag and drop the desired component into any of the facets. If you want the child component to stretch, it must be a component that supports being stretched. See Section 8.3.2, "What You May Need to Know About Geometry Management and the panelStretchLayout Component," for more details.

    Because facets accept one child only, if you want to add more than one child component, wrap the child components inside a container component, for example, a panelGroupLayout component. This component must also be able to be stretched in order for all contained components to stretch.

    Tip:

    If any facet is not visible in the visual editor:
    1. Right-click the panelStretchLayout component in the Structure window.

    2. From the context menu, choose Facets - Panel Stretch Layout >facet name. Facets in use on the page are indicated by a checkmark in front of the facet name.

8.3.2 What You May Need to Know About Geometry Management and the panelStretchLayout Component

The panelStretchLayout component can stretch its child components and it can also be stretched. The following components can be stretched inside the facets of the panelStretchLayout component:

  • inputText (when configured to stretch)

  • decorativeBox (when configured to stretch)

  • panelAccordion (when configured to stretch)

  • panelBox

  • panelCollection

  • panelDashboard (when configured to stretch)

  • panelGroupLayout (only with the layout attribute set to scroll or vertical)

  • panelSplitter (when configured to stretch)

  • panelStretchLayout (when configured to stretch)

  • panelTabbed (when configured to stretch)

  • region

  • table (when configured to stretch)

  • tree (when configured to stretch)

  • treeTable (when configured to stretch)

The following components cannot be stretched when placed inside a facet of the panelStretchLayout component:

  • panelBorderLayout

  • panelFormLayout

  • panelGroupLayout (only with the layout attribute set to default or horizontal)

  • panelHeader

  • panelLabelAndMessage

  • panelList

  • showDetail

  • showDetailHeader

  • tableLayout (MyFaces Trinidad component)

You cannot place components that cannot stretch into facets of a component that stretches its child components. Therefore, if you need to place a component that cannot be stretched into a facet of the panelStretchLayout component, wrap that component in a transition component that can stretch.

For example, if you want to place content in a panelBox component (which does not stretch) within a facet of the panelStretchLayout component, you could place a panelGroupLayout component with its layout attribute set to scroll in a facet of the panelStretchLayout component, and then place the panelBox component in that panelGroupLayout component. For more information, see Section 8.2.2, "Nesting Components Inside Components That Allow Stretching."

8.4 Using Splitters to Create Resizable Panes

When you have groups of unique content to present to users, consider using the panelSplitter component to provide multiple panes separated by adjustable splitters. The File Explorer uses a panelSplitter to separate the navigation tree from the folder contents, as shown in Figure 8-7. Users can change the size of the panes by dragging the splitter, and can also collapse and restore the panel that displays the directories. When a panel is collapsed, the panel contents are hidden; when a panel is restored, the contents are displayed.

Figure 8-7 File Explorer Uses panelSplitter to Separate Contents

Multiple Panes Separated by Splitters

The panelSplitter component lets you organize contents into two panes separated by an adjustable splitter. The panes can either line up on a horizontal line (as does the splitter shown in Figure 8-7) or on a vertical line. The File Explorer application uses another panelSplitter component to separate the application's header contents from the main body of the page. Figure 8-8 shows the panelSplitter component expanded to show the header contents, which includes the Oracle logo and the File Explorer name.

Figure 8-8 panelSplitter with a Vertical Split Expanded

panelSplitter shows header

Clicking the arrow button on a splitter collapses the panel that holds the header contents, and the logo and name are no longer shown, as shown in Figure 8-9.

Figure 8-9 File Explorer Uses panelSplitter with a Vertical Split

Horizontal and Vertical PanelSplitter

You place components inside the facets of the panelSplitter component. The panelSplitter component uses geometry management to stretch its child components at runtime. This means when the user collapses one panel, the contents in the other panel are explicitly resized to fill up available space.

Note:

While the user can change the values of the splitterPosition and collapsed attributes by resizing or collapsing the panes, those values will not be retained once the user leaves the page unless you configure your application to use change persistence. For information about enabling and using change persistence, see Chapter 31, "Allowing User Customization on JSF Pages."

8.4.1 How to Use the panelSplitter Component

The panelSplitter component lets you create two panes separated by a splitter. Each splitter component has two facets, namely, first and second, which correspond to the first panel and second panel, respectively. Child components can reside inside the facets only. To create more than two panes, you nest the panelSplitter components.

To create and use the panelSplitter component:

  1. In the Component Palette, from the Layout panel, drag and drop a Panel Splitter onto the JSF page.

  2. In the Property Inspector, expand the Common section.

  3. Set Orientation to vertical to create two vertical panes (one on top of the other). By default, the value is horizontal, which means horizontal panes are placed left-to-right (or right-to-left, depending on the language reading direction).

  4. Set SplitterPosition and PositionedFromEnd to determine the initial placement of the splitter. By default, the value of the splitterPosition attribute is 200 pixels, and the positionedFromEnd attribute is false. This setting means that ADF Faces measures the initial position of the adjustable splitter from the start or top panel (depending on the orientation attribute value). For example, if the orientation attribute is set to horizontal, the splitterPosition attribute is 200 and the positionedFromEnd attribute is false (all default values), then ADF Faces places the splitter 200 pixels from the start panel, as shown in Figure 8-10.

    Figure 8-10 Splitter Position Measured from Start Panel

    Splitter position measured from start pane

    If the positionedFromEnd attribute is set to true, then ADF Faces measures the initial position of the splitter from the end (or bottom panel, depending on the orientation value). Figure 8-11 shows the position of the splitter measured 200 pixels from the end panel.

    Figure 8-11 Splitter Position Measured from End Panel

    Splitter position measured from end pane
  5. Set collapsed to determine whether or not the splitter is in a collapsed (hidden) state. By default, the collapsed attribute is false, which means both panes are displayed. When the user clicks the arrow button on the splitter, the collapsed attribute is set to true and one of the panes is hidden.

    ADF Faces uses the collapsed and positionedFromEnd attributes to determine which panel (that is, the first or second panel) to hide (collapse) when the user clicks the arrow button on the splitter. When the collapsed attribute is set to true and the positionedFromEnd attribute is false, the first panel is hidden and the second panel stretches to fill up the available space. When the collapsed attribute is true and the positionedFromEnd attribute is true, the second panel is hidden instead. Visually, the user can know which panel will be collapsed by looking at the direction of the arrow on the button: when the user clicks the arrow button on the splitter, the panel collapses in the direction of the arrow.

  6. By default, the panelSplitter component stretches to fill available browser space. If you want to place the panelSplitter into a component that does not stretch its children, then you need to change how the panelSplitter component handles stretching.

    You configure whether the component will stretch or not using the dimensionsFrom attribute. To do so, expand the Other section, and set DimensionsFrom to one of the following:

    • children: Instead of stretching, the panelSplitter component will get its dimensions from its child component.

      Note:

      If you use this setting and you set the orientation attribute to vertical, then the contents of the collapsible panel will not be determined by its child component, but instead will be determined by the value of splitterPosition attribute. The size of the other pane will be determined by its child component.

      Additionally, you cannot set the height of the panelSplitter component (for example through the inlineStyle or styleClass attributes) if you use this setting. Doing so would cause conflict between the panelSplitter height and the child component height.

    • parent: The size of the panelSplitter component will be determined in the following order:

      • From the inlineStyle attribute.

      • If no value exists for inlineStyle, then the size is determined by the parent container.

      • If the parent container is not configured or not able to stretch its children, the size will be determined by the skin.

    • auto: If the parent component to the panelSplitter component allows stretching of its child, then the panelSplitter component will stretch to fill the parent. If the parent does not stretch its children then the size of the panelSplitter component will be based on the size of its child component.

  7. To place content in the component, drag and drop the desired component into the first and second facets. When you have the orientation set to horizontal, the first facet is the left facet. When you have the orientation set to vertical, the first facet is the top facet. If you want the child component to stretch, it must be a component that supports stretching. For more details, see Section 8.4.2, "What You May Need to Know About Geometry Management and the panelSplitter Component."

    Because facets accept one child component only, if you want to add more than one child component, wrap the child components inside a container component. This component must also be able to be stretched in order for all contained components to stretch.

    Tip:

    If any facet is not visible in the visual editor:
    1. Right-click the panelSplitter component in the Structure window.

    2. From the context menu, choose Facets - Panel Splitter >facet name. Facets in use on the page are indicated by a checkmark in front of the facet name.

  8. To create more than two panes, insert another Panel Splitter component into a facet to create nested splitter panes (as shown in Figure 8-12).

    Figure 8-12 Nested panelSplitter Components

    panelSplitters can be nested

    Example 8-3 shows the code generated by JDeveloper when you nest splitter components.

    Example 8-3 Nested panelSplitter Components

    <af:panelSplitter ...>
      <f:facet name="first">
        <!-- first panel child components components here -->
      </f:facet>
      <f:facet name="second">
        <!-- Contains nested splitter component -->
        <af:panelSplitter orientation="vertical" ...>
          <f:facet name="first">
            <!-- first panel child components components here -->
          </f:facet>
          <f:facet name="second">
            <!-- second panel child components components here -->
          </f:facet>
        </af:panelSplitter>
      </f:facet>
    </af:panelSplitter>
    
  9. If you want to perform some operation when users collapse or expand a panel, attach a client-side JavaScript using the clientListener tag for the collapsed attribute and a propertyChange event type. For more information about client-side events, see Chapter 5, "Handling Events."

8.4.2 What You May Need to Know About Geometry Management and the panelSplitter Component

The panelSplitter component can stretch its child components and it can also be stretched. The following components can be stretched inside the first or second facet of the panelSplitter component:

  • inputText (when configured to stretch)

  • decorativeBox (when configured to stretch)

  • panelAccordion (when configured to stretch)

  • panelBox

  • panelCollection

  • panelDashboard

  • panelGroupLayout (only with the layout attribute set to scroll or vertical)

  • panelSplitter (when configured to stretch)

  • panelStretchLayout (when configured to stretch)

  • panelTabbed (when configured to stretch)

  • region

  • table (when configured to stretch)

  • tree (when configured to stretch)

  • treeTable (when configured to stretch)

The following components cannot be stretched when placed inside a facet of the panelSplitter component:

  • panelBorderLayout

  • panelFormLayout

  • panelGroupLayout (only with the layout attribute set to default or horizontal)

  • panelHeader

  • panelLabelAndMessage

  • panelList

  • showDetail

  • showDetailHeader

  • tableLayout (MyFaces Trinidad component)

You cannot place components that cannot stretch into facets of a component that stretches its child components. Therefore, if you need to place one of the components that cannot be stretched into a facet of the panelSplitter component, wrap that component in a transition component that does not stretch its child components.

For example, if you want to place content in a panelBox component and have it flow within a facet of the panelSplitter component, you could place a panelGroupLayout component with its layout attribute set to scroll in a facet of the panelSplitter component, and then place the panelBox component in that panelGroupLayout component. For more information, see Section 8.2.2, "Nesting Components Inside Components That Allow Stretching."

8.5 Arranging Page Contents in Predefined Fixed Areas

The panelBorderLayout component uses facets to contain components in predefined areas of a page. Instead of a center facet, the panelBorder layout component takes 0 to n direct child components (also known as indexed children), which are rendered consecutively in the center. The facets then surround the child components.

Figure 8-13 shows the facets of the panelBorderLayout component.

Figure 8-13 Facets in panelBorderLayout

Predefined named areas around center area

The 12 supported facets of the panelBorderLayout component are:

The panelBorderLayout component does not support stretching its child components, nor does it stretch when placed in a component that stretches its child components. Therefore, the size of each facet is determined by the size of the component it contains. If instead you want the contents to stretch to fill the browser window, consider using the panelStretchLayout component instead. For more information, see Section 8.3, "Arranging Contents to Stretch Across a Page."

8.5.1 How to Use the panelBorderLayout Component

There is no restriction to the number of panelBorderLayout components you can have on a JSF page.

To create and use the panelBorderLayout component:

  1. In the Component Palette, from the Layout panel, drag and drop a Panel Border Layout onto the JSF page.

  2. From the Component Palette, drag and drop the component that will be used to display contents in the center of the window as a child component to the panelBorderLayout component.

    Child components are displayed consecutively in the order in which you inserted them. If you want some other type of layout for the child components, wrap the components inside the panelGroupLayout component. For more information, see Section 8.12, "Grouping Related Items."

  3. To place contents that will surround the center, drag and drop the desired component into each of the facets.

    Because facets accept one child component only, if you want to add more than one child component, wrap the child components inside a container.

    Tip:

    If any facet is not visible in the visual editor:
    1. Right-click the panelBorderLayout component in the Structure window.

    2. From the context menu, choose Facets - Panel Border Layout >facet name. Facets in use on the page are indicated by a checkmark in front of the facet name.

8.6 Arranging Content in Forms

The panelFormLayout component lets you lay out multiple form input components such as input fields and selection list fields in one or more columns. The File Explorer application uses a panelFormLayout component to display file properties. The component is configured to have the labels right-aligned, as shown in Figure 8-14.

Figure 8-14 Right-Aligned Labels and Left-Aligned Fields in a Form

Right-aligned labels and left-aligned fields

Figure 8-15 shows the same page with the component configured to display the labels above the fields.

Figure 8-15 Labels Above Fields in a Form

Labels above Fields in Form

You can configure the panelFormLayout component to display the fields with their labels in one or more columns. Each field in the form is a child component of the panelFormLayout component. You set the desired number of rows, and if there are more child components than rows, the remaining child components are placed in a new column. For example, if there are 25 child components, and you set the component to display 15 rows, the last 10 components will be displayed in a second column.

However, the number of rows displayed in each is not solely determined by the configured number of rows. By default, the panelFormLayout component is set to render no more than three columns (two for PDA applications). This value is what actually determines the number of rows. For example, if you have 25 child components and you set the component to display 5 rows and you leave the default maximum number of columns set to 3, then the component will actually display 9 rows, even though you have it set to display 5. This is because the maximum number of columns can override the set number of rows. Because it is set to allow only up to 3 columns, it must use 9 rows in order to display all child components. You would need to set the maximum number of columns to 5 in order to have the component display just 5 rows.

ADF Faces uses default label and field widths, as determined by the standard HTML flow in the browser. You can also specify explicit widths to use for the labels and fields. Regardless of the number of columns in the form layout, the widths you specify apply to all labels and fields. You specify the widths using either absolute numbers in pixels or percentage values. If the length of a label does not fit, the text is wrapped.

Tip:

If your page will be displayed in languages other than English, you should leave extra space in the labels to account for different languages and characters.

8.6.1 How to Use the panelFormLayout Component

You can use one or more panelFormLayout components on a page to create the desired form layout.

To create and use panelFormLayout:

  1. In the Component Palette, from the Layout panel, drag and drop a Panel Form Layout onto the JSF page.

  2. In the Property Inspector, expand the Common section and set the label alignment.

    By default, field labels on the child input components are displayed beside the fields. To place the labels above the fields, set the labelAlignment attribute to top.

    Note:

    When you nest a panelFormLayout component inside another panelFormLayout component, the label alignment in the nested layout is top.
  3. Set rows and maxColumns to determine the number of rows and columns in the form.

    The rows attribute value is the number that ADF Faces uses as the number of rows after which a new column will start. By default, it is set to 2147483647 (Integer.MAX_VALUE). This means all the child components that are set to rendered="true" and visible="true" will render in one, single column.

    If you want the form to contain more than one column, set the rows attribute to a multiple of the number of rendered child components, and then set the maxColumns attribute to the maximum amount of columns that the form should display. The default value of maxColumns is 3. (On PDAs, the default is 2).

    Note:

    If the panelFormLayout component is inside another panelFormLayout component, the inner panelFormLayout component's maxColumns value is always 1.

    For example, if the rows attribute is set to 6 and there are 1 to 6 rendered child components, the list will be displayed in 1 column. If there are 7 to 12 rendered child components, the list will be displayed in 2 columns. If there are 13 or more child components, the list will be displayed in 3 columns. To display all rendered child components in 1 column, set the rows attribute back to the default value.

    If the number of rendered child components would require more columns than allowed by the maxColumn attribute, then the value of the rows attribute is overridden. For example, if there are 100 rendered child components, and the rows attribute is set to 30 and the maxColumns attribute is 3 (default), the list will be displayed in 3 columns and 34 rows. If the maxColumns attribute is set to 2, the list will be displayed in 2 columns and 51 rows.

    Tip:

    Rendered child components refers only to direct child components of the form. Therefore, when a component that renders multiple rows (for example selectManyCheckbox) is a child, all its rows will be treated as a single rendered child and cannot be split across separate columns.
  4. Set fieldWidth and labelWidth as needed.

    ADF Faces uses default label and field widths, as determined by standard HTML flow in the browser. You can also specify explicit widths to use for the labels and fields.

    The labelWidth attribute on the panelFormLayout component lets you set the preferred width for labels; the fieldWidth attribute lets you set the preferred width for fields.

    Note:

    Any value you specify for the labelWidth component is ignored in layouts where the labelAlignment attribute is set to top, that is, in layouts where the labels are displayed above the fields.

    Regardless of the number of columns in the form layout, the widths you specify apply to all labels and fields, that is, you cannot set different widths for different columns. You specify the widths using any CSS unit such as em, px, or %. The unit used must be the same for both the labelWidth and fieldWidth attribute.

    When using percentage values:

    • The percentage width you specify is a percent of the entire width taken up by the panelFormLayout component, regardless of the number of columns to be displayed.

    • The sum of the labelWidth and fieldWidth percentages must add up to 100%. If the sum is less than 100%, the widths will be normalized to equal 100%. For example, if you set the labelWidth to 10% and the fieldWidth to 30%, at runtime the labelWidth would be 33% and the fieldWidth would be 67%.

    • If you explicitly set the width of one but not the other (for example, you specify a percentage for labelWidth but not fieldWidth), ADF Faces automatically calculates the percentage width that is not specified.

    Note:

    If your form contains multiple columns and a footer, you may see a slight offset between the positioning of the main form items and the footer items in web browsers that do not honor fractional divisions of percentages. To minimize this effect, ensure that the percentage labelWidth is evenly divisible by the number of columns.

    Suppose the width of the panelFormLayout component takes up 600 pixels of space, and the labelWidth attribute is set at 50%. In a one-column display, the label width will be 300 pixels and the field width will be 300 pixels. In a two-column display, each column is 300 pixels, so each label width in a column will be 150 pixels, and each field width in a column will be 150 pixels.

    If the length of the label text does not fit on a single line with the given label width, ADF Faces automatically wraps the label text. If the given field width is less than the minimum size of the child content you have placed inside the panelFormLayout component, ADF Faces automatically uses the minimum size of the child content as the field width.

    Note:

    If the field is wider than the space allocated, the browser will not truncate the field but instead will take space from the label columns. This potentially could cause the labels to wrap more than you would like. In this case, you may want to consider reducing the width of the field contents (for example, use a smaller contentStyle width on an inputText component).
  5. Insert the desired child components.

    Usually you insert labeled form input components, such as Input Text, Select Many Checkbox, and other similar components that enable users to provide input.

    Tip:

    The panelFormLayout component also allows you to use the iterator, switcher, and group components as direct child components, providing these components wrap child components that would typically be direct child components of the panelFormLayout component.

    Example 8-4 shows the panelFormLayout component as it is used on the properties.jspx page of the File Explorer application, shown in Figure 8-14.

    Example 8-4 panelFormLayout Component

    <af:panelFormLayout rows="5" labelAlignment="top">
      <af:inputText value="#{fileItemProperties.type}"
                    label="#{explorerBundle['fileproperties.type']}"
                    readOnly="true"/>  <af:inputText value="#{fileItemProperties.location}"
                    label="#{explorerBundle['fileproperties.currentpath']}"
                    readOnly="true"/>
      <af:inputText value="#{fileItemProperties.size}"
                    label="#{explorerBundle['fileproperties.size']}"
                    readOnly="true"/>
      <af:inputText value="#{fileItemProperties.contains}"
                    label="#{explorerBundle['fileproperties.contains']}"
                    readOnly="true"/>
    </af:panelFormLayout>
    

    Tip:

    If you use non-input components (which do not have label attributes) or if you want to group several input components with one single label inside a panelFormLayout component, first wrap the components inside a panelLabelAndMessage component. For information about using the panelLabelAndMessage component, see Section 17.4, "Grouping Components with a Single Label and Message."
  6. To group semantically related input components in a form layout, use the group component to wrap those components that belong in a group. Components placed within a group will cause the panelFormLayout component to draw a separator line above and below the group.

    For more information about using the group component, see Section 8.6.2, "What You May Need to Know About Using the group Component with the panelFormLayout Component."

  7. To add content below the child input components, insert the desired component into the footer facet.

    Facets accept only one child component. If you have to insert more than one component in the footer facet, use the panelGroupLayout component or the group component to wrap the footer child components. Example 8-5 shows sample code that uses the panelGroupLayout component to arrange footer child components in a panelFormLayout component.

    Example 8-5 Footer Child Components in panelFormLayout Arranged Horizontally

    <af:panelFormLayout>
      <f:facet name="footer">
        <af:panelGroupLayout layout="horizontal">
          <af:commandButton text="Save"/>
          <af:commandButton text="Cancel"/>
          <f:facet name="separator">
            <af:spacer width="3" height="3"/>
          </f:facet>
        </af:panelGroupLayout>
      </f:facet>
      .
      .
      .
    </af:panelFormLayout>
    

8.6.2 What You May Need to Know About Using the group Component with the panelFormLayout Component

While the group component itself does not render anything, when it used as a child in the panelFormLayout component, visible separators are displayed around the child components of each group component. For example, you might want to group some of the input fields in a form layout created by the panelFormLayout component. Example 8-15 shows sample code that groups two sets of child components inside a panelFormLayout component.

Example 8-6 Grouping Child Components in panelFormLayout

<af:panelFormLayout binding="#{editor.component}" rows="10" labelWidth="33%"
                    fieldWidth="67%" testId="panelFormLayout1">
  <af:inputText columns="5" label="label 1"/>
  <af:group>
    <af:inputText columns="5" label="grouped 1" shortDesc="This one is secret!"
         secret="true"/>
    <af:inputText columns="5" label="grouped 2"/>
    <af:inputText columns="5" label="grouped 3"/>
   </af:group>
   <af:inputDate id="df1" label="label 2"/>
   <af:panelLabelAndMessage label="label 3" labelStyle="vertical-align: middle;">
     <af:commandButton text="Submit"/>
   </af:panelLabelAndMessage>
   <af:selectOneListbox id="sol" label="label 4" shortDesc="Select One Option">
     <af:selectItem label="option 1"/>
     <af:selectItem label="option 2"/>
     <af:selectItem label="option 3"/>
     <af:selectItem label="option 4"/>
   </af:selectOneListbox>
   <af:selectManyListbox id="rs" label="label 5" shortDesc="Select Option">
     <af:selectItem label="option 1"/>
     <af:selectItem label="option 2"/>
     <af:selectItem label="option 3"/>
     <af:selectItem label="option 4"/>oiiiik,
     </af:selectManyListbox>
</af:panelFormLayout>

Following along with the sample code in Example 8-15, at runtime the panelFormLayout component renders dotted, separator lines before and after the first group of child components, as shown in Figure 8-16.

Figure 8-16 Grouped Components in panelFormLayout

Dotted lines set apart a group of components

As described in Section 8.6, "Arranging Content in Forms," the panelFormLayout component uses certain component attributes to determine how to display its child components (grouped and ungrouped) in columns and rows. When using the group component to group related components in a panelFormLayout component that will display its child components in more than one column, the child components of any group component will always be displayed in the same column, that is, child components inside a group component will never be split across a column.

While the group component does not provide any layout for its child components, the underlying HTML elements can provide the desired layout for the child components inside the group component. For example, if you want child button components in a group component to flow horizontally in a form layout, use the panelGroupLayout component to wrap the buttons, and set the layout attribute on panelGroupLayout component to horizontal. Then insert the panelGroupLayout component into group component, as shown in Example 8-7.

Example 8-7 panelGroupLayout Inside a Group Component

<af:group>
  <af:panelGroupLayout layout="horizontal">
    <af:commandButton text="Save" ../>
    <af:commandButton text="Cancel" ../>
    <f:facet name="separator">
      <af:spacer width="3"/>
    </f:facet>
  </af:panelGroupLayout>
</af:group>

When you use the group component to group child components in the footer facet of the panelFormLayout component, you must place all the group components and other ungrouped child components in one root group component, as shown in Example 8-8.

Example 8-8 footer Facet in panelFormLayout with One Root group Component

<af:panelFormLayout ...>
  <f:facet name="footer">
    <!-- One root group component needed -->
    <af:group>
      <af:outputText value="Footer item 1"/>
      <!-- One group -->
      <af:group>
        <af:outputText value="Group 1 item 1"/>
        <af:outputText value="Group 1 item 2"/>
      </af:group>
      <af:panelGroupLayout layout="horizontal">
        <af:commandButton text="Save"/>
        <af:commandButton text="Cancel"/>
        <f:facet name="separator">
          <af:spacer width="3"/>
        </f:facet>
      </af:panelGroupLayout>
    </af:group>
  </f:facet>
  .
  .
  .
</af:panelFormLayout>

Like grouped child components in a panelFormLayout component, at runtime the panelFormLayout component renders dotted, separator lines around the child components of each group component in the footer facet, as shown in Figure 8-17.

Figure 8-17 Footer in panelGroupLayout with Grouped Components

Grouped items in body and footer of PanelFormLayout

Note:

The footer facet in the panelFormLayout component supports only two levels of grouped components, that is, you cannot have three or more levels of nested group components in the footer facet. For example, the following code is not valid:
<f:facet name="footer">
  <!-- Only one root group -->
  <af:group>
    <af:outputText value="Footer item 1"/>
    <!-- Any number of groups at this level -->
    <af:group>
      <af:outputText value="Group 1 item 1"/>
      <af:outputText value="Group 1 item 2"/>
      <!-- But not another nested group. This is illegal. -->
      <af:group>
        <af:outputText value="Nested Group 1 item 1"/>
        <af:outputText value="Nested Group 1 item 2"/>
      </af:group>
    </af:group>
    <af:outputText value="Another footer item"/>
  </af:group>
</f:facet>

Whether you are grouping components in the footer facet or in the main body of the panelFormLayout component, if the first or last child inside the panelFormLayout component or inside the footer facet is a group component, no separator lines will be displayed around the child components in that group. For example, both sets of code examples in Example 8-9 would produce the same visual effect at runtime.

Example 8-9 Code Producing Same Visual Effect

<!-- Example 1: Group of buttons is last child in root group -->
<f:facet name="footer">
  <af:group>
    <af:outputText value="Footer text item 1"/>
    <af:outputText value="Footer text item 2"/>
    <af:group>
      <af:inputText label="Nested group item 1"/>
      <af:inputText label="Nested group item 2"/>
    </af:group>
    <af:group>
      <af:panelGroupLayout layout="horizontal">
        <af:commandButton text="Cancel"/>
        <af:commandButton text="Save"/>
      </af:panelGroupLayout>
    </af:group>
  </af:group>
</f:facet>

<!-- Example 2: panelGroupLayout of buttons is last child in root group-->
<f:facet name="footer">
  <af:group>
    <af:outputText value="Footer text item 1"/>
    <af:outputText value="Footer text item 2"/>
    <af:group>
      <af:inputText label="Nested group item 1"/>
      <af:inputText label="Nested group item 2"/>
    </af:group>
    <af:panelGroupLayout layout="horizontal">
      <af:commandButton text="Cancel"/>
      <af:commandButton text="Save"/>
    </af:panelGroupLayout>
  </af:group>
</f:facet>

8.7 Arranging Contents in a Dashboard

The panelDashboard component allows you to arrange its child components in rows and columns, similar to the panelForm component. However, instead of text components, the panelDashboard children are panelBox components that contain content, as shown in Figure 8-18.

Figure 8-18 panelDashboard with panelBox Child Components

panelDashboard arranges panelBoxes

When you add a panelDashboard component, you configure the number of columns it will contain, along with the height of each row. The dashboard stretches its children to fill up the configured space. If all the child components do not fit within the specified number of columns and row height, then the panelDashboard component displays a scroll bar.

When placed in a component that stretches it children, by default, the panelDashboard stretches to fill its parent container, no matter the number of children. This could mean that you may have blank space in the dashboard when the browser is resized to be much larger than the dashboard needs.

For example, say you have set the panelDashboard to inherit its size from its parent by setting the dimensionsFrom attribute to parent. You set columns to 1 and the rowHeight to 50px. You then add two panelBox components. Because columns is set to 1, you will have 2 rows. Because the parent component is a panelStretchLayout, the panelDashboard will stretch to fill the panelStretchLayout, no matter the height of the boxes, and you end up with extra space, as shown in Figure 8-19 (the color of the dashboard has been changed to fuchsia to make it more easy to see its boundaries).

Figure 8-19 panelDashboard Stretches to Fill Space

panelDashboard stretches to fill up space

If instead you don't want the dashboard to stretch, you can place it in a component that does not stretch its children, and you can configure the panelDashboard to determine its size based on its children (by setting the dimensionsFrom attribute to children). It will then be as tall as the number of rows required to display the children, multiplied by the rowHeight attribute.

In the previous example, if instead you place the dashboard in a panelGroupLayout set to scroll, because the rowHeight is set to 50, your panelDashboard will always be just over 100px tall, no matter the size of the browser window, as shown in Figure 8-20.

Figure 8-20 panelDashboard Does Not Stretch

panelDashboard does not stretch

The panelDashboard component also supports declarative drag and drop behavior, so that the user can rearrange the child components. As shown in Figure 8-21, the user can for example, move panelBox 10 between panelBox 4 and panelBox 5. A shadow is displayed where the box can be dropped.

Figure 8-21 Drag and Drop Capabilities in panelDashboard

Drag and drop panelboxes in panelDashboard

Note:

You can also configure drag and drop functionality that allows users to drag components into and out of the panelDashboard component. For more information, see Section 32.6, "Adding Drag and Drop Functionality Into and Out of a panelDashboard Component."

Along with the ability to move child components, the panelDashboard component also provides an API that you can access to allow users to switch child components from being rendered to not rendered, giving the appearance of panelBoxes being inserted or deleted. The dashboard uses partial page rendering to redraw the new set of child components without needing to redraw the entire page.

You can use the panelDashboardBehavior tag to make the rendering of components appear more responsive. This tag allows the activation of a command component to apply visual changes to the dashboard before the application code modifies the component tree on the server. Because this opening up of space happens before the action event is sent to the server, the user will see immediate feedback while the action listener for the command component modifies the component tree and prepares the dashboard for the optimized encoding of the insert.

For example, Figure 8-22 shows a panelDashboard component used in the right panel of a panelSplitter component. In the left panel, list items displayed as links represent each panelBox component in the panelDashboard. When all panelBox components are displayed, the links are all inactive. However, if a user deletes one of the panelBox components, the corresponding link becomes active. The user can click the link to reinsert the panelBox. By using the panelDashboardBehavior tag with the commandLink component, the user sees the inserted box drawing.

Figure 8-22 commandLink Components Use panelDashboardBehavior Tag

panelDashboardBehavior tag for links

If you decide not to use this tag, there will be a slight delay while your action listener is processing before the user sees any change to the dashboard structure.

Figure 8-23 shows a practical example using a panelDashboard component. Selecting one of the links at the top of the page changes the panelBoxes displayed in the dashboard. The user can also add panelBoxes by clicking the associated link on the left-hand side of the page.

Figure 8-23 Practical Example of panelDashboard

panelDashboard example

8.7.1 How to Use the panelDashboard Component

After you add a panelDashboard to a page, you can configure the dashboard to determine whether or not it will stretch. Then, add child components, and if you want to allow rearrangement the components, also add a componentDragSource tag to the child component. If you want to allow insertion and deletion of components, implement a listener to handle the action. You can also use the panelDashboardBehavior tag to make the panelDashboard component appear more responsive to the insertion.

To use the panelDashboard component:

  1. In the Component Palette, from the Layout panel drag and drop a Panel Dashboard onto the page.

  2. In the Property Inspector, expand the Common section.

  3. Set columns to the number of columns you want to use to display the child components. The child components will stretch to fit each column.

  4. Set RowHeight to the number of pixels high that each row should be. The child components will stretch to this height.

  5. By default, the panelDashboard component stretches to fill available browser space. If instead, you want to use the panelDashboard component as a child to a component that does not stretch its children, then you need to change how the panelDashboard component handles stretching.

    You configure whether the component will stretch or not using the dimensionsFrom attribute. To do so, expand the Other section, and set DimensionsFrom to one of the following:

    • children: the panelDashboard component will get its dimensions from its child components.

      Note:

      If you use this setting, you cannot set the height of the panelDashboard component (for example through the inlineStyle or styleClass attributes). Doing so would cause conflict between the panelDashboard height and the child component height.
    • parent: the size of the panelDashboard component will be determined in the following order:

      • From the inlineStyle attribute.

      • If no value exists for inlineStyle, then the size is determined by the parent container.

      • If the parent container is not configured or not able to stretch its children, the size will be determined by the skin.

    • auto: If the parent component to the panelDashboard component allows stretching of its child, then the panelDashboard component will stretch to fill the parent. If the parent does not stretch its children then the size of the panelDashboard component will be based on the size of its child component.

  6. From the Component Palette, drag and drop child panelBox components.

    Tip:

    The panelDashboard component also supports the region component as a child component.
  7. If you want users to be able to reorder the child components, in the Component Palette, from the Operations panel, drag and drop a Component Drag Source as a child to each of the child components.

  8. If you want to be able to add and delete components, create a managed bean and implement a handler method that will handle reordering children when a child is added or dropped. This event is considered a drop event, so you must use the Drag and Drop framework. For more information about creating a handler for a drop event, see Chapter 32, "Adding Drag and Drop Functionality."

    To use the optimized lifecycle, have the handler call the panelDashboard component's prepareOptimizedEncodingOfInsertedChild() method, which causes the dashboard to send just the inserted child component to be rendered.

    Note:

    If you plan on using the panelDashboardBehavior tag, then this API should be called from the associated command component's actionListener handler.
  9. If you have added a componentDragSource tag in Step 7, then you must also implement a DropEvent handler for the panelDashboard. With the panelDashboard component selected, expand the Behavior section and bind the DropListener attribute to that handler method.

  10. If you wish to use a panelDashboardBehavior tag, drag and drop a command component that will be used to initiate the insertion.

  11. In the Property Inspector, bind the ActionListener for the command component to a handler on a managed bean that will handle the changes to the component tree. Have the handler call the panelDashboard component's prepareOptimizedEncodingOfInsertedChild() method, which causes the dashboard to send just the inserted child component to be rendered. Example 8-10 shows code on a managed bean that handles the insertion of child components.

    Example 8-10 Action Listener Code for Insert Button

    public void handleInsert(ActionEvent e)
    {
      UIComponent eventComponent = e.getComponent();
      String panelBoxId = eventComponent.getAttributes().get("panelBoxId").toString();
      UIComponent panelBox = _dashboard.findComponent(panelBoxId);
    
      // Make this panelBox rendered:
      panelBox.setRendered(true);
    
      // Becaue the dashboard is already shown, perform an optimized 
      // render so the whole dashboard does not have to be re-encoded:
      int insertIndex = 0;
      List<UIComponent> children = _dashboard.getChildren();
      for (UIComponent child : children)
      {
        if (child.equals(panelBox))
        {
          // Let the dashboard know that only the one child component should be 
          // encoded during the render phase:
          _dashboard.prepareOptimizedEncodingOfInsertedChild(
            FacesContext.getCurrentInstance(),
            insertIndex);
          break;
        }
     
        if (child.isRendered())
        {
          // Count only rendered children because that is all that the 
          // panelDashboard can see:
          insertIndex++;
        }
      }
      // Add the side bar as a partial target because we need to 
      // redraw the state of the side bar item that corresponds to the inserted item:
      RequestContext rc = RequestContext.getCurrentInstance();
      rc.addPartialTarget(_sideBar);
    }
    
  12. In the Component Palette, from the Operations panel, drag a Panel Dashboard Behavior tag and drop it as a child to the command component.

  13. In the Property Inspector, enter the following:

    • for: Enter the ID for the associated panelDashboard component

    • index: Enter an EL expression that resolves to a method that determines the index of the component to be inserted. When you use the panelDashboardBehavior tag, a placeholder element is inserted into the DOM tree where the actual component will be rendered once it is returned from the server. Because the insertion placeholder gets added before the insertion occurs on the server, you must specify the location where you are planning to insert the child component so that if the user reloads the page, the children will continue to remain displayed in the same order.

8.7.2 What You May Need to Know About Geometry Management and the panelDashboard Component

This component organizes its children into a grid based on the number of columns and the rowHeight attribute. The child components that can be stretched inside of the panelDashboard include:

  • inputText (when the rows attribute is set to greater than one, and the simple attribute is set to true)

  • panelBox

  • region

  • table (when configured to stretch)

If you try to put any other component as a child component to the panelDashboard component, then the component hierarchy is not valid.

8.8 Displaying and Hiding Contents Dynamically

Sometimes you want users to have the choice of displaying or hiding content. When you do not need to show all the functionality of the user interface at once, you can save a lot of space by using components that enable users to show and hide parts of the interface at will.

The showDetail component creates a label with a toggle icon that allows users to disclose (show) or undisclose (hide) contents under the label. When the contents are undisclosed (hidden), the default label is Show and the toggle icon is a plus sign in a box. When the contents are disclosed (shown), the default label is Hide, and the toggle icon changes to a minus sign.

For example, the newFileItem page of the File Explorer application uses a showDetail component to hide and display file properties. The component is configured to hide the properties when the page is displayed, as shown in Figure 8-24.

Figure 8-24 Collapsed showDetail

collapsed showDetail

When the user clicks the toggle icon, the properties are displayed, as shown in Figure 8-25.

Figure 8-25 Expanded showDetail

Expanded and collapsed ShowDetail components

If you want to use something more complex than an outputText component to display the disclosed and undisclosed text, you can add components to the showDetail component's prompt facet. When set to be visible, any contents in the prompt facet will replace the disclosed and undisclosed text values. To use the showDetail component, see Section 8.8.1, "How to Use the showDetail Component."

Like the showDetail component, the showDetailHeader component also toggles the display of contents, but the showDetailHeader component provides the label and toggle icon in a header, and also provides facets for a menu bar, toolbar, and text.

Tip:

The showDetailHeader component is the same as a panelHeader component, except that it handles disclosure events. For more information about the panelHeader component, see Section 8.10, "Displaying Items in a Static Box."

When there is not enough space to display everything in all the facets of the title line, the showDetailHeader text is truncated and displays an ellipsis. When the user hovers over the truncated text, the full text is displayed in a tooltip, as shown in Figure 8-26.

Figure 8-26 Text for the showDetailHeader Is Truncated

Text for the panelHeader is Truncated

When there is more than enough room to display the contents, the extra space is placed between the context facet and the toolbar, as shown in Figure 8-27.

Figure 8-27 Extra Space Is Added Before the Toolbar

Extra Space is Added Before the Toolbar

Additionally, you can configure the showDetailHeader component to be used as a message for errors, warnings, information, or confirmations. The contents are hidden or displayed below the header. For example, the newFileItem page of the File Explorer application uses a showDetailHeader component to display help for creating a new file. By default, the help is not displayed, as shown in Figure 8-25. When the user clicks the toggle icon in the header, the contents are displayed, as shown in Figure 8-28.

Figure 8-28 showDetailHeader Component Used to Display Help

showDetailHeader can display help text

You can also use the showDetailHeader component in conjunction with the panelHeader component to divide a page into sections and subsections, where some contents can be hidden. The showDetailHeader component contains a number of facets, such as a toolbar and menu bar facet. These facets are the same as for the panelHeader component. For more information about the panelHeader component, see Section 8.10, "Displaying Items in a Static Box."

You can nest showDetailHeader components to create a hierarchy of content. Each nested component takes on a different heading style to denote the hierarchy. Figure 8-29 shows three nested showDetailHeader components, and their different styles.

Figure 8-29 Nested showDetailHeader Components Create a Hierarchy

showDetailHeader components can be nested

You can change the styles used by each header level by applying a skin to the showDetailHeader component. For details about skinning ADF Faces components, see Chapter 20, "Customizing the Appearance Using Styles and Skins."

Note:

While you can force the style of the text using the size attribute, (where 0 is the largest text), the value of the size attribute will not affect the hierarchy. It only affects the style of the text.

Use the panelBox component when you want information to be able to be displayed or hidden below the header, and you want the box to be offset from other information on the page. The File Explorer application uses two panelBox components on the properties.jspx page to display the attributes and history of a file, as shown in Figure 8-30.

Figure 8-30 Two panelBox Components

Two Panel Boxes or Content Containers

Figure 8-31 shows the same page, but with the History panelBox component in an undisclosed state.

Figure 8-31 Undisclosed panelBox Component

Undisclosed panelBox

You can set the background color on a panelBox component so that the contents are further delineated from the rest of the page. Two color combinations (called ramps) are offered, and each combination contains four levels of color: none, light, medium, and dark. Figure 8-32 shows the same panel boxes as in Figure 8-30, but with the bottom panelBox component configured to show the medium tone of the core ramp.

Figure 8-32 Panel Boxes Using a Background Color

Background color set in panelBox

You can set the size of a panelBox component either explicitly by assigning a pixel size, or as a percentage of its parent. You can also set the alignment of the title, and add an icon. In addition, the panelBox component includes the toolbar facet that allows you to add a toolbar and toolbar buttons to the box.

If you want to show and hide multiple large areas of content, consider using the panelAccordion and panelTabbed components. For more information, see Section 8.9, "Displaying or Hiding Contents in Accordion Panels and Tabbed Panels."

8.8.1 How to Use the showDetail Component

Use the showDetail component to show and hide a single set of content.

To create and use the showDetail component:

  1. In the Component Palette, from the Common Components panel, drag and drop a Show Detail from the Component Palette onto the JSF page.

    Tip:

    This component appears in the Common Components panel of the Component Palette, and not the Layout panel.
  2. In the Property Inspector, expand the Common section and set the attributes as needed.

    Set Disclosed to true if you want the component to show its child components.

    Note:

    While the user can change the value of the disclosed attribute by displaying and hiding the contents, the value will not be retained once the user leaves the page unless you configure your application to allow user customizations. For information, see Chapter 31, "Allowing User Customization on JSF Pages."

    Set DisclosedText to the label you want to display next to the toggle icon when the contents are disclosed (shown). By default, the label is Hide if no value is specified.

    Set UndisclosedText to the label you want to display next to the toggle icon when the contents are undisclosed (hidden). By default, the label is Show if no value is specified.

    Note:

    If you specify a value for disclosedText but not for undisclosedText, then ADF Faces automatically uses the disclosedText value for both the disclosed state and undisclosed state. Similarly, if you specify a value for undisclosedText but not for disclosedText, the undisclosedText value is used when the contents are hidden or displayed.

    Instead of using text specified in disclosedText and undisclosedText, you could use the prompt facet to add a component that will render next to the toggle icon.

  3. Expand the Behavior section and set DisclosureListener to a DisclosureListener method in a backing bean that you want to execute when the user displays or hides the component's contents.

    For information about disclosure events and listeners, see Section 8.8.4, "What You May Need to Know About Disclosure Events."

  4. To add content, insert the desired child components inside the showDetail component.

8.8.2 How to Use the showDetailHeader Component

Use the showDetailHeader component when you want to display a single set of content under a header, or when you want the content to be used as messages that can be displayed or hidden. You can also use the showDetailHeader component to create a hierarchy of headings and content when you want the content to be able to be hidden.

To create and use the showDetailHeader component:

  1. In the Component Palette, from the Layout panel, drag and drop a Show Detail Header onto the JSF page.

  2. In the Property Inspector, expand the Common section. Set Text to the text string you want for the section header label.

  3. Set Icon to the URI of the image file you want to use for the section header icon. The icon image is displayed before the header label.

    Note:

    Because alternative text cannot be provided for this icon, in order to create an accessible product, use this icon only when it is purely decorative. You must provide the meaning of this icon in some accessible manner.
  4. If you are using the header to provide specific messaging information, set MessageType to one of the following values:

    • confirmation: The confirmation icon (represented by a note page overlaid with a green checkmark) replaces any specified icon image.

    • error: The error icon (represented by a red circle with an x inside) replaces any specified icon image. The header label also changes to red.

    • info: The info icon (represented by a blue circle with an I inside) replaces any specified icon image.

    • warning: The warning icon (represented by a yellow triangle with an exclamation mark inside) replaces any specified icon image.

    • none: Default. No icon is displayed, unless one is specified for the icon attribute.

    Figure 8-33 shows each of the icons used for message types.

    Figure 8-33 Icons Used for Message Types

    message type icons

    Note:

    Because alternative text cannot be provided for this icon, in order to create an accessible product, use this icon only when it is purely decorative. You must provide the meaning of this icon in some accessible manner.
  5. Set Disclosed to true if you want the component to show its child components.

    Note:

    While the user can change the value of the disclosed attribute by displaying and hiding the contents, the value will not be retained once the user leaves the page unless you configure your application to allow user customization. For information, see Chapter 31, "Allowing User Customization on JSF Pages."
  6. Expand the Behavior section and set DisclosureListener to a disclosureListener method in a backing bean that you want to execute when the user displays or hides the component's contents.

    For information about disclosure events and listeners, see Section 8.8.4, "What You May Need to Know About Disclosure Events."

  7. If you want to control how the showDetailHeader component handles geometry management, expand the Other section and set Type. Set it to flow if you do not want the component to stretch or to stretch its children. The height of the showDetailHeader component will be determined solely by its children. Set it to stretch if you want it to stretch and stretch its child (will only stretch a single child component). Leave it set to the default if you want the parent component of the showDetailHeader component to determine geometry management. For more information about geometry management, see Section 8.2.1, "Geometry Management and Component Stretching."

  8. To add buttons or icons to the header, in the Component Palette, from the Common Components panel, drag and drop the toolbar component into the toolbar facet. Then add any number of commandToolbarButton or commandButton components into the newly inserted toolbar component. For more information about using the toolbar component, see Section 14.3, "Using Toolbars."

    Note:

    Toolbar overflow is not supported in panelHeader components.
  9. To add menus to the header, insert menu components into the menuBar facet. For more information about creating menus, see Section 14.2, "Using Menus in a Menu Bar."

    Tip:

    You can place menus in the toolbar facet and toolbars (and toolboxes) in the menu facet. The main difference between these facets is location. The toolbar facet is before the menu facet.
  10. To create a subsection header, insert another showDetailHeader component inside an existing showDetailHeader component.

    The size attribute specifies the number to use for the header level. The largest number is 0, and it corresponds to an H1 header level; the smallest is 5, and it corresponds to an H6 header.

    By default, the size attribute is -1. This means ADF Faces automatically calculates the header number (and thus the header level style to use) from the topmost, parent component. When you use nested components, you do not have to set the size attribute explicitly to get the proper header style to be displayed.

    Note:

    While you can force the style of the text using the size attribute, (where 0 is the largest text), the value of the size attribute will not affect the hierarchy. It only affects the style of the text.

    In the default skin used by ADF Faces, the style used for sizes above 2 will be displayed the same as size 2. That is, there is no difference in styles for sizes 3, 4, or 5–they all show the same style as size 2. You can change this by creating a custom skin. For more information, see Chapter 20, "Customizing the Appearance Using Styles and Skins."

  11. To add content to a section or subsection, insert the desired child components inside the showDetailHeader component.

8.8.3 How to Use the panelBox Component

You can insert any number of panelBox components on a page.

To create and use a panelBox component:

  1. In the Component Palette, from the Layout panel, drag and drop a Panel Box to the JSF page.

  2. In the Property Inspector, expand the Appearance section, and for Ramp, select the ramp you wish to use.

    The core ramp uses variations of blue, while the highlight ramp uses variations of yellow. You can change the colors used by creating a custom skin. For details, see Chapter 20, "Customizing the Appearance Using Styles and Skins."

  3. Set Background to one of the following values: light, medium, dark, or default. The default background color is transparent.

  4. Set Text to the text string you want to display as the title in the header portion of the container.

  5. Set Icon to the URI of the icon image you want to display before the header text.

    Note:

    If both the text and icon attributes are not set, ADF Faces does not display the header portion of the panelBox component.

    Note:

    Because alternative text cannot be provided for this icon, in order to create an accessible product, use this icon only when it is purely decorative. You must provide the meaning of this icon in some accessible manner.
  6. Set TitleHalign to one of the following values: center, start, end, left, or right. The value determines the horizontal alignment of the title (including any icon image) in the header portion of the container.

  7. Expand the Behavior section and set DisclosureListener to a disclosureListener method in a backing bean that you want to execute when the user shows or hides the component's contents.

    For information about disclosure events and listeners, see Section 8.8.4, "What You May Need to Know About Disclosure Events."

  8. To add toolbar buttons, in the Component Palette, from the Common Components Panel, drag and drop a Toolbar into the toolbar facet. Then insert the desired number of commandToolbarButton components into the toolbar component. For information about using toolbar and commandToolbarButton components, see Section 14.3, "Using Toolbars."

    Tip:

    If any facet is not visible in the visual editor:
    1. Right-click the panelBox component in the Structure window.

    2. From the context menu, choose Facets - Panel Box >Toolbar. Facets in use on the page are indicated by a checkmark in front of the facet name.

  9. To add contents to the container for display, insert the desired components as child components to the panelBox component.

    Typically, you would insert one child component into the panelBox component, and then insert the contents for display into the child component. The child component controls how the contents will be displayed, not the parent panelBox component.

  10. To change the width of the panelBox component, set the inlineStyle attribute to the exact pixel size you want. Alternatively, you can set the inlineStyle attribute to a percentage of the outer element that contains the panelBox component. Example 8-11 shows the code you might use for changing the width.

    Example 8-11 panelBox Component with inlineStyle Attribute Set

    <af:panelBox inlineStyle="width:50%;" ...>
      <!-- child contents here -->
    </af:panelBox>
    

8.8.4 What You May Need to Know About Disclosure Events

Any ADF Faces component that has built-in event functionality, as the showDetail, showDetailHeader, and panelBox components do, must be enclosed in the form component.

The disclosed attribute on these components specifies whether to show (disclose) or hide (undisclose) the contents under its header. By default, the disclosed attribute is true, that is, the contents are shown. When the attribute is set to false, the contents are hidden. You do not have to write any code to enable the toggling of contents from disclosed to undisclosed, and vice versa. ADF Faces handles the toggling automatically.

The value of the disclosed attribute can be persisted at runtime, that is, when the user shows or hides contents, ADF Faces can change and then persist the attribute value so that it remains in that state for the length of the user's session. For more information, see Chapter 31, "Allowing User Customization on JSF Pages."

When the user clicks the toggle icon to show or hide contents, the components deliver a org.apache.myfaces.trinidad.event.DisclosureEvent event to the server. The DisclosureEvent event contains information about the source component and its state: whether it is disclosed (expanded) or undisclosed (collapsed). The isExpanded() method returns a boolean value that determines whether to expand (disclose) or collapse (undisclose) the node. If you only want the component to disclose and undisclose its contents, then you do not need to write any code.

However, if you want to perform special handling of a DisclosureEvent event, you can bind the component's disclosureListener attribute to a disclosureListener method in a backing bean. The disclosureListener method will then be invoked in response to a DisclosureEvent event, that is, whenever the user clicks the disclosed or undisclosed icon.

The disclosureListener method must be a public method with a single disclosureEvent event object and a void return type, shown in Example 8-12.

Example 8-12 disclosureListener Method

public void some_disclosureListener(DisclosureEvent disclosureEvent) {
// Add event handling code here
}

By default, DisclosureEvent events are usually delivered in the Invoke Application phase, unless the component's immediate attribute is set to true. When the immediate attribute is set to true, the event is delivered in the earliest possible phase, usually the Apply Request Values phase.

On the client-side component, the AdfDisclosureEvent event is fired. The event root for the client AdfDisclosureEvent event is set to the event source component: only the event for the panel whose disclosed attribute is true gets sent to the server. For more information about client-side events and event roots, see Chapter 5, "Handling Events."

8.9 Displaying or Hiding Contents in Accordion Panels and Tabbed Panels

When you need to display multiple areas of content that can be hidden and displayed, you can use the panelAccordion or the panelTabbed components. Both of these components use the showDetailItem component to display the actual contents.

The panelAccordion component creates a series of expandable panes. You can allow users to expand more than one panel at any time, or to expand only one panel at a time. When more than one panel is expanded, the user can adjust the height of the panel by dragging the header of the showDetailItem component.

When a panel is collapsed, only the panel header is displayed; when a panel is expanded, the panel contents are displayed beneath the panel header (users can expand the panes by clicking either the panelAccordion component's header or the expand icon). The File Explorer application uses the panelAccordion component to display the Folders and Search panes, as shown in Figure 8-34.

Figure 8-34 panelAccordion Panes

Expanded and collapsed panels

At runtime, when available browser space is less than the space needed to display expanded panel contents, ADF Faces automatically displays overflow icons that enable users to select and navigate to those panes that are out of view. Figure 8-35 shows the overflow icon (circled in the lower right-hand corner) displayed in the Folders panel of the File Explorer application when there is not enough room to display the Search panel.

Figure 8-35 Overflow Icon In panelAccordion

Overflow icon above third accordian panel

When the user clicks the overflow icon, ADF Faces displays the overflow popup menu (as shown in Figure 8-36) for the user to select and navigate to.

Figure 8-36 Overflow Popup Menu in panelAccordion

Overflow popup menu above third accordian panel

You can also configure the panelAccordion so that the panes can be rearranged by dragging and dropping, as shown in Figure 8-37.

Figure 8-37 Panes Can Be Reordered by Dragging and Dropping

Search pane dragged

When the order is changed, the displayIndex attribute on the showDetailItem components also changes to reflect the new order.

Note:

Items in the overflow cannot be reordered.

To use the panelAccordion component, see Section 8.9.1, "How to Use the panelAccordion Component."

The panelTabbed component creates a series of tabbed panes. Unlike the panelAccordion panes, the panelTabbed panes are not collapsible or expandable. Instead, when users select a tab, the contents of the selected tab are displayed. The tabs may be positioned above the display area, below the display area, or both. You can configure a panelTabbed component so that the individual tabs can be closed. You can have it so that all tabs can be closed, all but the last tab can be closed, or no tabs can be closed. When tabs are configured to be removed, an X is displayed at the end of the tab. You can also configure tabs so that they display a disabled X, meaning it can be removed, but is currently disabled.

The File Explorer application uses the panelTabbed component to display the contents in the main panel, as shown in Figure 8-38.

Figure 8-38 panelTabbed Panes

Tabbed panels

To use the panelTabbed component, see Section 8.9.2, "How to Use the panelTabbed Component."

Tip:

If you want the tabs to be used in conjunction with navigational hierarchy, for example, each tab is a different page or region that contains another set of navigation items, you may want to use a navigation panel component to create a navigational menu. For more information, see Section 18.5, "Using Navigation Items for a Page Hierarchy."

For both the panelAccordion and panelTabbed components, use one showDetailItem component to provide the contents for each panel. For example, if you want to use four panes, insert four showDetailItem components inside the panelAccordion or panelTabbed components, respectively. To use the showDetailItem component, see Section 8.9.3, "How to Use the showDetailItem Component to Display Content in panelAccordion or panelTabbed Components." You can add a toolbar to the toolbar facet of the showDetailItem component, and the toolbar will be shown whenever the panel or tab is disclosed. Figure 8-38 shows the toolbar used by the showDetailItem component in the File Explorer application.

The panelTabbed component also supports an overflow icon if all tabs cannot be displayed. Figure 8-39 shows the overflow icon in the File Explorer application.

Figure 8-39 Overflow Icon in panelTabbed Component

Arrows next to tab indicate overflow

Performance Tip:

The number of child components within a panelAccordion or panelTabbed component, and the complexity of the child components, will affect the performance of the overflow. Set the size of the panelAccordion or panelTabbed component to avoid overflow when possible.

The panelAccordion and panelTabbed components can be configured to be stretched, or they can be configured to instead take their dimensions from the currently disclosed showDetailItem child.

When you configure the panelAccordion or panelTabbed component to stretch, then you can also configure the showDetailItem component to stretch a single child as long as it is the only child of the showDetailItem component.

8.9.1 How to Use the panelAccordion Component

You can use more than one panelAccordion component in a page, typically in different areas of the page, or nested. After adding the panelAccordion component, insert a series of showDetailItem components to provide the panes, using one showDetailItem for one panel. Then insert components into each showDetailItem to provide the panel contents. For procedures on using the showDetailItem component, see Section 8.9.3, "How to Use the showDetailItem Component to Display Content in panelAccordion or panelTabbed Components."

To create and use the panelAccordion component:

  1. In the Component Palette, from the Layout panel, drag and drop a Panel Accordion onto the JSF page.

  2. In the Property Inspector, expand the Common section.

  3. Set DiscloseMany to true if you want users to be able to expand and see the contents of more than one panel at the same time.

    By default, the value is false. This means only one panel can be expanded at any one time. For example, suppose there is one expanded panel A and one collapsed panel B when the page first loads. If the user expands panel B, panel A will be collapsed, because only one panel can be expanded at any time.

  4. Set the DiscloseNone to true if you want users to be able to collapse all panes.

    By default, the value is false. This means one panel must remain expanded at any time.

  5. If you want users to be able to rearrange the panes by dragging and dropping, expand the Other section, and set Reorder to enabled. The default is disabled.

    Note:

    If the panelAccordion has components other than showDetailItem components (see the tip in Step 7), those components can be reordered on the client only. Therefore, any new order will not be preserved.
  6. By default, the panelAccordion component stretches to fill available browser space. If instead, you want to use the panelAccordion component as a child to a component that does not stretch its children, then you need to change how the panelAccordion component handles stretching.

    You configure whether the component will stretch or not using the dimensionsFrom attribute. To do so, expand the Other section, and set DimensionsFrom to one of the following:

    • children: the panelAccordion component will get its dimensions from the currently disclosed showDetailItem component.

      Note:

      If you use this setting, you cannot set the height of the panelAccordion component (for example through the inlineStyle or styleClass attributes). Doing so would cause conflict between the panelAccordion height and the child component height.

      Similarly, you cannot set the stretchChildren, flex, and inflexibleHeight attributes on any showDetailItem component, as those settings would result in a circular reference back to the panelAccordion to determine size.

    • parent: the size of the panelAccordion component will be determined in the following order:

      • From the inlineStyle attribute.

      • If no value exists for inlineStyle, then the size is determined by the parent container.

      • If the parent container is not configured or not able to stretch its children, the size will be determined by the skin.

    • auto: If the parent component to the panelAccordion component allows stretching of its child, then the panelAccordion component will stretch to fill the parent. If the parent does not stretch its children then the size of the panelAccordion component will be based on the size of its child component.

    Note:

    If you want the panelAccordion to stretch, and you also want the showDetailItem to stretch its contents, then you must configure the showDetailItem in a certain way. For details, see Section 8.9.3, "How to Use the showDetailItem Component to Display Content in panelAccordion or panelTabbed Components."
  7. By default, one panel is added for you using a showDetailItem component as a child component to the panelAccordion component. To add more panes, insert the showDetailItem component inside the panelAccordion component. You can add as many panes as you wish.

    Tip:

    Accordion panels also allow you to use the iterator, switcher, and group components as direct child components, providing these components wrap child components that would typically be direct child components of the accordion panel.

    To add contents for display in a panel, insert the desired child components into each showDetailItem component. For procedures, see Section 8.9.3, "How to Use the showDetailItem Component to Display Content in panelAccordion or panelTabbed Components."

8.9.2 How to Use the panelTabbed Component

Using the panelTabbed component to create tabbed panes is similar to using the panelAccordion component to create accordion panes. After adding a panelTabbed component, you insert a series of showDetailItem components to provide the tabbed panel contents for display.

To create and use the panelTabbed component:

  1. In the Component Palette, from the Layout panel, drag and drop a Panel Tabbed onto the JSF page.

  2. In the Property Inspector, expand the Common section.

  3. Set Position to below if you want the tabs to be rendered below the contents in the display area.

    By default, the value is above. This means the tabs are rendered above the contents in the display area. The other acceptable value is both, where tabs are rendered above and below the display area.

  4. If you want users to be able to close (remove) tabs, then set TabRemoval. You can set it to allow all tabs to be removed, or all but the last tab. You must implement a handler to do the actual removal and configure the listeners for the associated showDetailItem components. You can override this on an individual showDetail Item component, so that an individual tab cannot be removed (a close icon does not display), or so that the closed icon is disabled. For more information, see Section 8.9.3, "How to Use the showDetailItem Component to Display Content in panelAccordion or panelTabbed Components."

  5. By default, the panelTabbed component stretches to fill available browser space. If instead, you want to use the panelTabbed component as a child to a component that does not stretch its children, then you need to change how the panelTabbed component handles stretching.

    You configure whether the component will stretch or not using the dimensionsFrom attribute. To do so, expand the Other section, and set DimensionsFrom to one of the following:

    • disclosedChild: the panelTabbed component will get its dimensions from the currently disclosed showDetailItem component.

      Note:

      If you use this setting, you cannot set the height of the panelTabbed component (for example through the inlineStyle or styleClass attributes). Doing so would cause conflict between the panelTabbed height and the child component height.
    • parent: the size of the panelTabbed component will be determined in the following order:

      • From the inlineStyle attribute.

      • If no value exists for inlineStyle, then the size is determined by the parent container.

      • If the parent container is not configured or not able to stretch its children, the size will be determined by the skin.

    • auto: If the parent component to the PanelTabbed component allows stretching of its child, then the panelTabbed component will stretch to fill the parent. If the parent does not stretch its children then the size of the panelTabbed component will be based on the size of its child component.

  6. By default, one tabbed panel is created for you using a showDetailItem component as a child to the panelTabbed component. To add more panes, insert the showDetailItem component inside the panelTabbed component. You can add as many tabbed panes as you wish.

    Tip:

    The panelTabbed component also allow you to use the iterator, switcher, and group components as direct child components, providing these components wrap child components that would typically be direct child components of the panelTabbed component.

    To add contents for display in a panel, insert the desired child components into each showDetailItem component. For information about using showDetailItem, see Section 8.9.3, "How to Use the showDetailItem Component to Display Content in panelAccordion or panelTabbed Components."

8.9.3 How to Use the showDetailItem Component to Display Content in panelAccordion or panelTabbed Components

Insert showDetailItem components into a panelAccordion or panelTabbed component only. Each showDetailItem component corresponds to one accordion panel or tabbed panel. Typically, you insert two or more showDetailItem components into the parent component. Insert the child components for display into the showDetailItem components.

The disclosed attribute on a showDetailItem component specifies whether to show (disclose) or hide (undisclose) the corresponding accordion panel or tab contents. By default, the disclosed attribute is false, that is, the contents are hidden (undisclosed). When the attribute is set to true, the contents are shown (disclosed). You do not have to write any code to enable the toggling of contents from disclosed to undisclosed, and vice versa. ADF Faces handles the toggling automatically.

The following procedure assumes you have already added a panelAccordion or panelTabbed component to the JSF page, as described in Section 8.9.1, "How to Use the panelAccordion Component," and Section 8.9.2, "How to Use the panelTabbed Component," respectively.

To add accordion panel or tabbed panel contents using a showDetailItem component:

  1. Insert one or more showDetailItem components inside the parent component, such as panelAccordion or panelTabbed, by dragging and dropping a Show Detail Item component from Common Components panel of the Component Palette.

  2. In the Property Inspector, expand the Appearance section.

  3. Set Text to the label you want to display for this panel or tab.

  4. To add an icon before the label, set Icon to the URI of the image file to use.

    Note:

    Because alternative text cannot be provided for this icon, in order to create an accessible product, use this icon only when it is purely decorative. You must provide the meaning of this icon in some accessible manner.
  5. If the showDetailItem component is being used inside a panelAccordion component configured to stretch, you can configure the showDetailItem to stretch and in turn stretch its contents, however, the showDetailItem component must contain only one child component. You need to set Flex and the StretchChildren for each showDetailItem component.

    Note:

    If you have set the panelAccordion to not stretch (that is, you've set dimensionsFrom to children), then you cannot set values for the flex and stretchChildren attributes, as it will result in a circular reference back to the panelAccordion for size.

    Use the following attributes on each showDetailItem component to control the flexibility of panel contents:

    • Flex: Specifies a nonnegative integer that determines how much space is distributed among the showDetailItem components of one panelAccordion component. By default, the value of the flex attribute is 0 (zero), that is, the panel contents of each showDetailItem component are inflexible. To enable flexible contents in a panel, specify a flex number larger than 0, for example, 1 or 2. A larger flex value means that the contents will be made larger than components with lower flex values. For two flexible components, their height sizes are exactly proportionate to the flex values assigned. If component A has flex set to 2 and component B has flex set to 1, then the height of component A is two times the height of component B.

    • InflexibleHeight: Specifies the number of pixels a panel will use. The default is 100 pixels. This means if a panel has a flex value of 0 (zero), ADF Faces will use 100 pixels for that panel, and then distribute the remaining space among the nonzero panes. If the contents of a panel cannot fit within the panelAccordion container given the specified inflexibleHeight value, ADF Faces automatically moves nearby contents into overflow menus (as shown in Figure 8-36). Also, if a panel has a nonzero flex value, this will be the minimum height that the panel will shrink to before causing other panes to be moved into the overflow menus.

    • StretchChildren: When set to first, stretches a single child component. However, the child component must allow stretching. For more information, see Section 8.9.4, "What You May Need to Know About Geometry Management and the showDetailItem Component."

    For example, the File Explorer application uses showDetailItem components to display contents in the navigator panel. Because the Search Navigator requires more space when both navigators are expanded, its flex attribute is set to 2 and the showDetailItem component for the Folders Navigator uses the default flex value of 1. This setting causes the Search Navigator to be larger than the Folders Navigator when it is expanded.

    Note:

    Instead of directly setting the value for the flex attribute, the File Explorer application uses an EL expression that resolves to a method used to determine the value. Using an EL expression allows you to programmatically change the value if you decide at a later point to use metadata to provide model information.

    The user can change the panel heights at runtime, thereby changing the value of the flex and inflexibleHeight attributes. Those values can be persisted so that they remain for the duration of the user's session. For information, see Chapter 31, "Allowing User Customization on JSF Pages."

    Note the following additional information about flexible accordion panel contents:

    • There must be two or more panes (showDetailItem components) with flex values larger than 0 before ADF Faces can enable flexible contents. This is because ADF Faces uses the flex ratio between two components to determine how much space to allocate among the panel contents. At runtime, two or more panes must be expanded before the effect of flexible contents can be seen.

    • If the showDetailItem component has only one child component and the flex value is nonzero, and the stretchChildren attribute is set to first, ADF Faces will stretch that child component regardless of the discloseMany attribute value on the panelAccordion component.

    • When all showDetailItem components have flex values of 0 (zero) and their panel contents are disclosed, even though the disclosed contents are set to be inflexible, ADF Faces will stretch the contents of the last disclosed showDetailItem component as if the component had a flex value of 1, but only when that showDetailItem component has one child only, and the stretchChildren attribute is set to first. If the last disclosed panel has more than one child component or the stretchChildren attribute is set to none, the contents will not be stretched.

    Even with the flex attribute set, there are some limitations regarding geometry management. For more information, see Section 8.9.4, "What You May Need to Know About Geometry Management and the showDetailItem Component."

  6. Expand the Behavior section. Set DisclosureListener to the disclosureListener method in a backing bean you want to execute when this panel or tab is selected by the user.

    For information about server disclosure events and event listeners, see Section 8.8.4, "What You May Need to Know About Disclosure Events."

  7. Set Disabled to true if you want to disable this panel or tab (that is, the user will not be able to select the panel or tab).

  8. Set Disclosed to true if you want this panel or tab to show its child components.

    By default, the disclosed attribute is set to false. This means the contents for this panel or tab are hidden.

    Note:

    Note the difference between the disclosed and rendered attributes. If the rendered attribute value is false, it means that this accordion header bar or tab link and its corresponding contents are not available at all to the user. However, if the disclosed attribute is set to false, it means that the contents of the item are not currently visible, but may be made visible by the user because the accordion header bar or tab link are still visible.

    If none of the showDetailItem components has the disclosed attribute set to true, ADF Faces automatically shows the contents of the first enabled showDetailItem component (except when it is a child of a panelAccordion component, which has a setting for zero disclosed panes).

    Note:

    While the user can change the value of the disclosed attribute by displaying or hiding the contents, the value will not be retained once the user leaves the page unless you configure your application to allow user customization. For information, see Chapter 31, "Allowing User Customization on JSF Pages."
  9. For showDetailItem components used in a panelAccordion component, expand the Other section, and set DisplayIndex to reflect the order in which the showDetailItem components should appear. If you simply want them to appear in the order in which they are in the page's code, then leave the default, -1.

    Tip:

    If some showDetailItem components have -1 as the value for displayIndex, and others have a positive number, those with the -1 value will display after those with a positive number, in the order they appear in the page's code.

    Tip:

    This value can be changed at runtime if the parent panelAccordion component is configured to allow reordering.
  10. If you chose to allow tab removal for a panelTabbed component, expand the Other section and set Remove to one of the following:

    • inherit: The corresponding tab can be removed if the parent panelTabbed component is configured to allow it. This is the default.

    • no: The corresponding tab cannot be removed, and will not display a close icon.

    • disabled: The corresponding tab will display a disabled close icon.

    Set ItemListener to an EL expression that resolves to a handler method that will handle the actual removal of a component.

  11. To add toolbar buttons to a panel (supported in the panelAccordion component only), in the Component Palette, from the Common Components panel, insert a Toolbar into the toolbar facet of the showDetailItem component that defines that panel. Then, insert the desired number of commandToolbarButton components into the toolbar component. Although the toolbar facet is on the showDetailItem component, it is the panelAccordion component that renders the toolbar and its buttons. For information about using toolbar and commandToolbarButton, see Section 14.3, "Using Toolbars."

    Note:

    When an accordion panel is collapsed, ADF Faces does not display the toolbar and its buttons. The toolbar and its buttons are displayed in the panel header only when the panel is expanded.
  12. To add contents to the panel, insert the desired child components into each showDetailItem component.

8.9.4 What You May Need to Know About Geometry Management and the showDetailItem Component

Both the panelAccordion or panelTabbed components can be configured to stretch when they are placed inside a component that uses geometry management to stretch its child components. However, for the panelAccordion component, the showDetailItem component will stretch only if the discloseMany attribute on the panelAccordion component is set to true (that is, when multiple panes may be expanded to show their inflexible or flexible contents), the showDetailItem component contains only one child component, and the showDetailItem component's stretchChildren attribute is set to first. By default, panel contents will not stretch.

The showDetailItem component will allow stretching if:

  • It contains only a single child

  • Its stretchChildren attribute is set to first

  • The child has no width, height, border, and padding set

  • The child must be capable of being stretched

When all of the preceding bullet points are true, the showDetailItem component can stretch its child component. The following components can be stretched inside the showDetailItem component:

  • inputText (when configured to stretch)

  • decorativeBox (when configured to stretch)

  • panelAccordion (when configured to stretch)

  • panelBox

  • panelCollection

  • panelDashboard (when configured to stretch)

  • panelGroupLayout (only when the layout attribute is set to scroll or vertical)

  • panelSplitter (when configured to stretch)

  • panelStretchLayout (when configured to stretch)

  • panelTabbed (when configured to stretch)

  • region

  • table (when configured to stretch)

  • tree (when configured to stretch)

  • treeTable (when configured to stretch)

The following components cannot be stretched when placed inside a showDetailItem component:

  • panelBorderLayout

  • panelFormLayout

  • panelGroupLayout (only when the layout attribute is set to default or horizontal)

  • panelHeader

  • panelLabelAndMessage

  • panelList

  • tableLayout (MyFaces Trinidad component)

You cannot place components that cannot stretch as a child to a component that stretches its child components. Therefore, if you need to place one of the components that cannot be stretched as a child of a showDetailItem component, you need to wrap that component in different component that does not stretch its child components.

For example, if you want to place content in a panelList component and have it be displayed in a showDetailItem component, you might place a panelGroupLayout component with its layout attribute set to scroll as the chid of the showDetailItem component, and then place the panelList component in that component. For more information, see Section 8.2.1, "Geometry Management and Component Stretching."

8.9.5 What You May Need to Know About showDetailItem Disclosure Events

The showDetailItem component inside of panelAccordion and panelTabbed components supports queuing of disclosure events so that validation is properly handled on the server and on the client.

In general, for any component with the disclosed attribute, by default, the event root for the client AdfDisclosureEvent is set to the event source component: only the event for the panel whose disclosed attribute is true gets sent to the server. However, for the showDetailItem component that is used inside of panelTabbed or panelAccordion component, the event root is the panelTabbed or panelAccordion component (that is, the event source parent component, not the event source component). This ensures that values from the previously disclosed panel will not get sent to the server.

For example, suppose you have two showDetailItem components inside a panelTabbed or panelAccordion component with the discloseMany attribute set to false and the discloseNone attribute set to false. Suppose the showDetailItem 1 component is disclosed but not showDetailItem 2. Given this scenario, the following occurs:

  • On the client:

    • When a user clicks to disclose showDetailItem 2, a client-only disclosure event gets fired to set the disclosed attribute to false for the showDetailItem 1 component. If this first event is not canceled, another client disclosure event gets fired to set the disclosed attribute to true for the showDetailItem 2 component. If this second event is not canceled, the event gets sent to the server; otherwise, there are no more disclosure changes.

  • On the server:

    • The server disclosure event is fired to set the disclosed attribute to true on the showDetailItem 2 component. If this first server event is not canceled, another server disclosure event gets fired to set the disclosed attribute to false for the showDetailItem 1 component. If neither server event is canceled, the new states get rendered, and the user will see the newly disclosed states on the client; otherwise, the client looks the same as it did before.

For the panelAccordion component with the discloseMany attribute set to false and the discloseNone attribute set to true, the preceding information is the same only when the disclosure change forces a paired change (that is, when two disclosed states are involved). If only one disclosure change is involved, there will just be one client and one server disclosure event.

For the panelAccordion component with the discloseMany attribute set to true (and any discloseNone setting), only one disclosure change is involved; there will just be one client and one server disclosure event.

For additional information about disclosure events, see Section 8.8.4, "What You May Need to Know About Disclosure Events."

8.10 Displaying Items in a Static Box

You can use the panelHeader component when you want header type functionality, such as message display or associated help topics, but you do not have to provide the capability to show and hide content.

You can use the decorativeBox component when you need to transition to a different look and feel on the page. The decorativeBox component uses themes and skinning keys to control the borders and colors of its different facets. For example, depending on the skin you are using, if you use the default theme, the decorativeBox component body is white and the border is blue, and the top-left corner is rounded. If you use the medium theme, the body is a medium blue. For information about using themes and skins, see Chapter 20, "Customizing the Appearance Using Styles and Skins"

The panelHeader component offers facets for specific types of components and the ability to open a help topic from the header. The following are the facets supported by the panelHeader component:

Figure 8-40 shows the different facets in the panelHeader component.

Figure 8-40 panelHeader and Its Facets

Faces in panelHeader

When there is not enough space to display everything in all the facets of the title line, the panelHeader text is truncated and displays an ellipsis. When the user hovers over the truncated text, the full text is displayed in a tooltip, as shown in Figure 8-41.

Figure 8-41 Text for the panelHeader Is Truncated

Text for the panelHeader is Truncated

When there is more than enough room to display the contents, the extra space is placed between the context facet and the toolbar, as shown in Figure 8-42.

Figure 8-42 Extra Space Is Added Before the Toolbar

Extra Space is Added Before the Toolbar

You can configure panelHeader components so that they represent a hierarchy of sections. For example, as shown in Figure 8-43, you can have a main header with a subheader and then a heading level 1 also with a subheader.

Figure 8-43 Creating Subsections with the panelHeader Component

Subsedction in panelHeader

Create subsections by nesting panelHeader components within each other. When you nest panelHeader components, the heading text is automatically sized according to the hierarchy, with the outermost panelHeader component having the largest text.

Note:

While you can force the style of the text using the size attribute (where 0 is the largest text), the value of the size attribute will not affect the hierarchy. It only affects the style of the text.

For information about using the panelHeader component, see Section 8.10.1, "How to Use the panelHeader Component."

The decorativeBox component provides styling capabilities using themes. It has two facets, top and center. The top facet provides a non-colored area, while the center facet is the actual box. The height of the top facet depends on whether or not a component has been put into the top facet. When the facet is set, the topHeight attribute is used to specify the size the content should occupy.

The color of the box for the center facet depends on the theme and skin used. Figure 8-44 shows the different themes available by default.

Figure 8-44 Themes Used in a decorativeBox Component

Themes Used in a decorativeBox Component

By default, the decorativeBox component stretches to fill its parent component. You can also configure the decorative Box component to inherit its dimensions from its child components. For example, Figure 8-45 shows the medium-theme decorativeBox configured to stretch to fill its parent, while the dark-theme decorativeBox is configured to only be as big as its child outputText component.

Figure 8-45 decorativeBox Can Stretch or Not

decorativeBox Can Stretch or Not

You can further control the style of the decorativeBox component using skins. Skinning keys can be defined for the following areas of the component:

For more information about skins, see Chapter 20, "Customizing the Appearance Using Styles and Skins."

8.10.1 How to Use the panelHeader Component

You can use one panelHeader component to contain specific information, or you can use a series of nested panelHeader components to create a hierarchical organization of content. If you want to be able to hide and display the content, use the showDetailHeader component instead. For more information, see Section 8.8.2, "How to Use the showDetailHeader Component."

To create and use a panelHeader component:

  1. In the Component Palette, from the Layout panel, drag and drop a Panel Header onto the page.

  2. In the Property Inspector, expand the Appearance section.

  3. Set Text to the label you want to display for this panel.

  4. To add an icon before the label, set Icon to the URI of the image file to use.

    Note:

    Because alternative text cannot be provided for this icon, in order to create an accessible product, use this icon only when it is purely decorative. You must provide the meaning of this icon in some accessible manner.
  5. If you are using the header to provide specific messaging information, set MessageType to one of the following values:

    • confirmation: The confirmation icon (represented by a note page overlaid with a green checkmark) replaces any specified icon image.

    • error: The error icon (represented by a red circle with an "x" inside) replaces any specified icon image. The header label also changes to red.

    • info: The info icon (represented by a blue circle with an "I" inside) replaces any specified icon image.

    • none: Default. No icon is displayed.

    • warning: The warning icon (represented by a yellow triangle with an exclamation mark inside) replaces any specified icon image.

    Figure 8-46 shows the icons used for the different message types.

    Figure 8-46 Icons for Message Types

    Icons used for message types

    Note:

    Because alternative text cannot be provided for this icon, in order to create an accessible product, use this icon only when it is purely decorative. You must provide the meaning of this icon in some accessible manner.
  6. To display help for the header, enter the topic ID for HelpTopicId. For more information about creating and using help topics, see Section 17.5, "Displaying Help for Components."

  7. If you want to control how the panelHeader component handles geometry management, expand the Other section and set Type to one of the following. For more information about geometry management, see Section 8.2.1, "Geometry Management and Component Stretching."

    • flow: The component will not stretch or stretch its children. The height of the panelHeader component will be determined solely by its children.

    • stretch: The component will stretch and stretch its child (will only stretch a single child component).

    • default: if you want the parent component of the panelHeader component to determine geometry management.

  8. To add toolbar buttons to a panel, insert the toolbar component into the toolbar facet. Then, insert the desired number of commandToolbarButton components into the toolbar component. For information about using toolbar and commandToolbarButton, see Section 14.3, "Using Toolbars."

    Note:

    Toolbar overflow is not supported in panelHeader components.
  9. To add menus to a panel, insert menu components into the menuBar facet. For information about creating menus in a menu bar, see Section 14.2, "Using Menus in a Menu Bar."

    Tip:

    You can place menus in the toolbar facet and toolbars (and toolboxes) in the menu facet. The main difference between these facets is location. The toolbar facet is before the menu facet.
  10. Add contents to the other facets as needed.

    Tip:

    If any facet is not visible in the visual editor:
    1. Right-click the panelHeader component in the Structure window.

    2. From the context menu, choose Facets - Panel Header >facet name. Facets in use on the page are indicated by a checkmark in front of the facet name.

  11. To add contents to the panel, insert the desired child components into the panelHeader component.

8.10.2 How to Use the decorativeBox Component

You use the decorativeBox component to provide a colored area or box in a page. This component is typically used as a container for the navigationPane component that is configured to display tabs. For more information, see Section 18.5, "Using Navigation Items for a Page Hierarchy."

To create and use a decorativeBox component:

  1. In the Component Palette, from the Layout panel, drag and drop a Decorative Box onto the page.

  2. In the Property Inspector, expand the Common section and set Top Height to the height for the top facet.

  3. To change the theme, expand the Style and Theme section and choose a different theme.

  4. By default, the decorativeBox component stretches to fill available browser space. If instead, you want to use the decorativeBox component as a child to a component that does not stretch its children, then you need to change how the decorativeBox component handles stretching.

    You configure whether the component will stretch or not using the dimensionsFrom attribute. To do so, expand the Other section, and set DimensionsFrom to one of the following:

    • children: the decorativeBox component will get its dimensions from its child components.

      Note:

      If you use this setting, you cannot use a percentage to set the height of the top facet. If you do, the top facet will try to get its dimensions from the size of this decorativeBox component, which will not be possible, as the decorativeBox component will be getting its height from its contents, resulting in a circular dependency. If a percentage is used, it will be disregarded and the default 50px will be used instead.

      Similarly, you cannot set the height of the decorativeBox (for example through the inlineStyle or styleClass attributes). Doing so would cause conflict between the decorativeBox height and the child component height.

    • parent: the size of the decorativeBox component will be determined in the following order:

      • From the inlineStyle attribute.

      • If no value exists for inlineStyle, then the size is determined by the parent container.

      • If the parent container is not configured or not able to stretch its children, the size will be determined by the skin.

    • auto: If the parent component to the decorativeBox component allows stretching of its child, then the decorativeBox component will stretch to fill the parent. If the parent does not stretch its children then the size of the decorativeBox component will be based on the size of its child component.

    For more information, see Section 8.10.3, "What You May Need to Know About Geometry Management and the decorativeBox Component."

8.10.3 What You May Need to Know About Geometry Management and the decorativeBox Component

The decorativeBox component can stretch child components in its center facet and it can also be stretched. The following components can be stretched inside the center facet of the decorativeBox component:

  • inputText (when configured to stretch)

  • decorativeBox (when configured to stretch)

  • panelAccordion (when configured to stretch)

  • panelBox

  • panelCollection

  • panelDashboard

  • panelGroupLayout (only with the layout attribute set to scroll or vertical)

  • panelSplitter (when configured to stretch)

  • panelStretchLayout (when configured to stretch)

  • panelTabbed (when configured to stretch)

  • region

  • table (when configured to stretch)

  • tree (when configured to stretch)

  • treeTable (when configured to stretch)

The following components cannot be stretched when placed inside a facet of the decorativeBox component:

  • panelBorderLayout

  • panelFormLayout

  • panelGroupLayout (only with the layout attribute set to default or horizontal)

  • panelHeader

  • panelLabelAndMessage

  • panelList

  • showDetail

  • showDetailHeader

  • tableLayout (MyFaces Trinidad component)

You cannot place components that cannot stretch into facets of a component that stretches its child components. Therefore, if you need to place one of the components that cannot be stretched into a facet of the decorativeBox component, wrap that component in a transition component that does not stretch its child components.

For example, if you want to place content in a panelBox component and have it flow within a facet of the decorativeBox component, you could place a panelGroupLayout component with its layout attribute set to scroll in the facet of the decorativeBox component, and then place the panelBox component in that panelGroupLayout component. For more information, see Section 8.2.2, "Nesting Components Inside Components That Allow Stretching."

8.11 Displaying a Bulleted List in One or More Columns

The panelList component is a layout element for displaying a vertical list of child components with a bullet next to each child, as shown in Figure 8-47. Only child components whose rendered attribute is set to true and whose visible attribute is set to true are considered for display by in the list.

Note:

To display dynamic data (for example, a list of data determined at runtime by JSF bindings), use the selection components, as documented in Section 9.6, "Using Selection Components." If you need to create lists that change the model layer, see Chapter 11, "Using List-of-Values Components."

Figure 8-47 PanelList Component with Default Disc Bullet

Bulleted list of items

By default, the disc bullet is used to style the child components. There are other styles you can use, such as square bullets and white circles. You can also split the list into columns when you have a very long list of items to display.

8.11.1 How to Use the panelList Component

Use one panelList component to create each list of items.

To create and use the panelList component:

  1. In the Component Palette, from the Layout panel, drag and drop a Panel List to the JSF page.

  2. In the Property Inspector, expand the Common section, and set the listStyle attribute to a valid CSS 2.1 list style value, such as one of the following:

    • list-style-type: disc

    • list-style-type: square

    • list-style-type: circle

    • list-style-type: decimal

    • list-style-type: lower-alpha

    • list-style-type: upper-alpha

    For example, the list-style-type: disc attribute value corresponds to a disc bullet, and the list-style-type: circle value corresponds to a circle bullet.

    For a complete list of the valid style values to use, refer to the CSS 2.1 Specification for generated lists at

    http://www.w3.org/TR/CSS21/generate.html

    Example 8-13 shows the code for setting the list style to a circle.

    Example 8-13 PanelList Component with ListStyle Attribute Set

    <af:panelList listStyle="list-style-type: circle" ...>
      <!-- child components here -->
    </af:panelList>
    
  3. Insert the desired number of child components (to display as bulleted items) into the panelList component.

    Tip:

    Panel lists also allow you to use the iterator, switcher, and group components as direct child components, providing these components wrap child components that would typically be direct child components of the panel list.

    For example, you could insert a series of commandLink components or outputFormatted components.

Note:

By default, ADF Faces displays all rendered child components of a panelList component in a single column. For details on how to split the list into two or more columns and for information about using the rows and maxColumns attributes, see Section 8.6, "Arranging Content in Forms." The concept of using the rows and maxColumns attributes for columnar display in the panelList and panelFormLayout components are the same.

8.11.2 What You May Need to Know About Creating a List Hierarchy

You can nest panelList components to create a list hierarchy. A list hierarchy, as shown in Figure 8-48, has outer items and inner items, where the inner items belonging to an outer item are indented under the outer item. Each group of inner items is created by one nested panelList component.

Figure 8-48 Hierarchical List Created Using Nested panelList Components

Hierarchical list of items

To achieve the list hierarchy as shown in Figure 8-48, use a group component to wrap the components that make up each group of outer items and their respective inner items. Example 8-14 shows the code for how to create a list hierarchy that has one outer item with four inner items, and another outer item with two inner items.

Example 8-14 Nested PanelList Components

<af:panelList>
  <!-- First outer item and its four inner items -->
  <af:group>
    <af:commandLink text="item 1"/>
    <af:panelList>
      <af:commandLink text="item 1.1"/>
      <af:commandLink text="item 1.2"/>
      <af:commandLink text="item 1.3"/>
      <af:commandLink text="item 1.4"/>
    </af:panelList>
   </af:group>
  <!-- Second outer item and its two inner items -->
  <af:group>
    <af:commandLink text="item 2"/>
    <af:panelList>
      <af:commandLink text="item 2.1"/>
      <af:commandLink text="item 2.2"/>
    </af:panelList>
   </af:group>
</af:panelList> 

By default, the outer list items (for example, item 1 and item 2) are displayed with the disc bullet, while the inner list items (for example, item 1.1 and item 2.1) have the white circle bullet.

For more information about the panelGroupLayout component, see Section 8.12, "Grouping Related Items."

8.12 Grouping Related Items

To keep like items together within a parent component, use either the group or panelGroupLayout component. The group component aggregates or groups together child components that are related semantically. Unlike the panelGroupLayout component, the group component does not provide any layout for its child components. Used on its own, the group component does not render anything; only the child components inside of a group component render at runtime.

You can use any number of group components to group related components together. For example, you might want to group some of the input fields in a form layout created by the panelFormLayout component. Example 8-15 shows sample code that groups two sets of child components inside a panelFormLayout component.

Example 8-15 Grouping Child Components in panelFormLayout

<af:panelFormLayout>
  <af:inputDate label="Pick a date"/>
  <!-- first group -->
  <af:group>
    <af:selectManyCheckbox label="Select all that apply">
      <af:selectItem label="Coffee" value="1"/>
      <af:selectItem label="Cream" value="1"/>
      <af:selectItem label="Low-fat Milk" value="1"/>
      <af:selectItem label="Sugar" value="1"/>
      <af:selectItem label="Sweetener"/>
    </af:selectManyCheckbox>
    <af:inputText label="Special instructions" rows="3"/>
  </af:group>
  <!-- Second group -->
  <af:group>
    <af:inputFile label="File to upload"/>
    <af:inputText label="Enter passcode"/>
  </af:group>
  <af:inputText label="Comments" rows="3"/>
  <af:spacer width="10" height="15"/>
  <f:facet name="footer"/>
</af:panelFormLayout>

The panelGroupLayout component lets you arrange a series of child components vertically or horizontally without wrapping, or consecutively with wrapping, as shown in Figure 8-49. The layout attribute value determines the arrangement of the child components.

Figure 8-49 panelGroupLayout Arrangements

Consecutive, horizontal, vertical layouts

In all arrangements, each pair of adjacent child components can be separated by a line or white space using the separator facet of the panelGroupLayout component. For more information, see Section 8.13, "Separating Content Using Blank Space or Lines."

When using the horizontal layout, the child components can also be vertically or horizontally aligned. For example, you could make a short component beside a tall component align at the top, as shown in Figure 8-50.

Figure 8-50 Top-Aligned Horizontal Layout with panelGroupLayout

Horizontal layout with PanelGroupLayout

Unlike the panelSplitter or panelStretchLayout components, the panelGroupLayout component does not stretch its child components. Suppose you are already using a panelSplitter or panelStretchLayout component as the root component for the page, and you have a large number of child components to flow, but are not to be stretched. To provide scrollbars when flowing the child components, wrap the child components in the panelGroupLayout component with its layout attribute set to scroll, and then place the panelGroupLayout component inside a facet of the panelSplitter or panelStretchLayout component.

When the layout attribute is set to scroll on a panelGroupLayout component, ADF Faces automatically provides a scrollbar at runtime when the contents contained by the panelGroupLayout component are larger than the panelGroupLayout component itself. You do not have to write any code to enable the scrollbars, or set any inline styles to control the overflow.

For example, when you use layout components such as the panelSplitter component that let users display and hide child components contents, you do not have to write code to show the scrollbars when the contents are displayed, and to hide the scrollbars when the contents are hidden. Simply wrap the contents the be displayed inside a panelGroupLayout component, and set the layout attribute to scroll.

In the File Explorer application, the Search Navigator contains a panelSplitter component used to hide and show the search criteria. When the search criteria are hidden, and the search results content does not fit into the area, a scrollbar is rendered, as shown in Figure 8-51.

Figure 8-51 Scrollbars Rendered Using panelGroupLayout

Scroll bars in panelGroupLayout

8.12.1 How to Use the panelGroupLayout Component

Any number of panelGroupLayout components can be nested to achieve the desired layout.

To create and use the panelGroupLayout component:

  1. In the Component Palette, from the Layout panel, drag and drop a Panel Group Layout to the JSF page.

  2. Insert the desired child components into the panelGroupLayout component.

    Tip:

    The panelGroupLayout component also allows you to use the iterator, switcher, and group components as direct child components, providing these components wrap child components that would typically be direct child components of the panelGroupLayout component.
  3. To add spacing or separator lines between adjacent child components, insert the spacer or separator component into the separator facet.

  4. In the Property Inspector, expand the Appearance section. To arrange the child components in the desired layout, set Layout to one of the following values:

    • default: Provides consecutive layout with wrapping.

      At runtime, when the contents exceed the browser space available (that is, when the child components are larger than the width of the parent container panelGrouplayout), the browser flows the contents onto the next line so that all child components are displayed.

      Note:

      ADF Faces uses the bidirectional algorithm when making contents flow. Where there is a mix of right-to-left content and left-to-right content, this may result in contents not flowing consecutively.
    • horizontal: Uses a horizontal layout, where child components are arranged in a horizontal line. No wrapping is provided when contents exceed the amount of browser space available.

      In a horizontal layout, the child components can also be aligned vertically and horizontally. By default, horizontal child components are aligned in the center with reference to an imaginary horizontal line, and aligned in the middle with reference to an imaginary vertical line. To change the horizontal and vertical alignments of horizontal components, use the following attributes:

      • halign: Sets the horizontal alignment. The default is center. Other acceptable values are: start, end, left, right.

        For example, set halign to start if you want horizontal child components to always be left-aligned in browsers where the language reading direction is left-to-right, and right-aligned in a right-to-left reading direction.

      • valign: Sets the vertical alignment. Default is middle. Other acceptable values are: top, bottom, baseline.

        In output text components (such as outputText) that have varied font sizes in the text, setting valign to baseline would align the letters of the text along an imaginary line on which the letters sit, as shown in Figure 8-52. If you set valign to bottom for such text components, the resulting effect would not be as pleasant looking, because bottom vertical alignment causes the bottommost points of all the letters to be on the same imaginary line.

        Figure 8-52 Bottom and Baseline Vertical Alignment of Text

        Vertical alignment in text output

      Note:

      The halign and valign attributes are ignored if the layout is not horizontal.
    • scroll: Uses a vertical layout, where child components are stacked vertically, and a vertical scrollbar is provided when necessary.

    • vertical: Uses a vertical layout, where child components are stacked vertically.

8.12.2 What You May Need to Know About Geometry Management and the panelGroupLayout Component

While the panelGroupLayout component cannot stretch its child components, it can be stretched when it is the child of a panelSplitter or panelStretchLayout component and its layout attribute is set to either scroll or vertical.

8.13 Separating Content Using Blank Space or Lines

You can incorporate some blank space in your pages, to space out the components so that the page appears less cluttered than it would if all the components were presented immediately next to each other, or immediately below each other. The ADF Faces component provided specifically for this purpose is the spacer component.

You can include either or both vertical and horizontal space in a page using the height and width attributes.

The height attribute determines the amount of vertical space to include in the page. Example 8-16 shows a page set up to space out two lengthy outputText components with some vertical space.

Example 8-16 Vertical Space

<af:panelGroupLayout layout="vertical">
  <af:outputText value="This is a long piece of text for this page..."/>
  <af:spacer height="10"/>
  <af:outputText value="This is some more lengthy text ..."/>
</af:panelGroupLayout>

Figure 8-53 shows the effect the spacer component has on the page output as viewed in a browser.

Figure 8-53 Vertical Space Viewed in a Browser

Vertical space between consecutive components

The width attribute determines the amount of horizontal space to include between components. Example 8-17 shows part of the source of a page set up to space out two components horizontally.

Example 8-17 Horizontal Space

<af:outputLabel value="Your credit rating is currently:"/>
<af:spacer width="10"/>
<af:outputText value="Level 8"/>

Figure 8-54 shows the effect of spacing components horizontally as viewed in a browser.

Figure 8-54 Horizontal Space Viewed in a Browser

Horizontal space between components

The separator component creates a horizontal line. Figure 8-55 shows the properties.jspx file as it would be displayed with a separator component inserted between the two panelBox components.

Figure 8-55 Using the separator Component to Create a Line

Separator component creates lines

The spacer and separator components are often used in facets of other layout components. Doing so ensures that the space or line stays with the components they were meant to separate.

8.13.1 How to Use the spacer Component

You can use as many spacer components as needed on a page.

To create and use the spacer component:

  1. In the Component Palette, from the Layout panel, drag and drop a Spacer to the JSF page.

  2. In the Property Inspector, expand the Common section. Set the width and height as needed.

    Note:

    If the height is specified but not the width, a block-level HTML element is rendered, thereby introducing a new line effect. If the width is specified, then, irrespective of the specified value of height, it may not get shorter than the applicable line-height in user agents that strictly support HTML standards.

8.13.2 How to Use the Separator Component

You can use as many separator components as needed on a page.

To create and use the separator component:

  1. In the Component Palette, from the Layout panel, drag and drop a Separator to the JSF page.

  2. In the Property Inspector, set the properties as needed.