19 Creating and Reusing Fragments, Page Templates, and Components

This chapter describes how you can create reusable content and then use that content to build portions of your JSF pages or entire pages.

This chapter includes the following sections:

19.1 Introduction to Reusable Content

As you build JSF pages for your application, some pages may become complex and long, making editing complicated and tedious. Some pages may always contain a group of components arranged in a very specific layout, while other pages may always use a specific group of components in multiple parts of the page. And at times, you may want to share some parts of a page or entire pages with other developers. Whatever the case is, when something changes in the UI, you have to replicate your changes in many places and pages. Building and maintaining all those pages, and making sure that some sets or all are consistent in structure and layout can become increasingly inefficient.

Instead of using individual UI components to build pages, you can use page building blocks to build parts of a page or entire pages. The building blocks contain the frequently or commonly used UI components that create the reusable content for use in one or more pages of an application. Depending on your application, you can use just one type of building block, or all types in one or more pages. And you can share some building blocks across applications. When you modify the building blocks, the JSF pages that use the reusable content are automatically updated as well. Thus, by creating and using reusable content in your application, you can build web user interfaces that are always consistent in structure and layout, and an application that is scalable and extensible.

ADF Faces provides the following types of reusable building blocks:

  • Page fragments: Page fragments allow you to create parts of a page. A JSF page can be made up of one or more page fragments. For example, a large JSF page can be broken up into several smaller page fragments for easier maintenance. For details about creating and using page fragments, see Section 19.2, "Using Page Fragments."

  • Page templates: By creating page templates, you can create entire page layouts using individual components and page fragments. For example, if you are repeatedly laying out some components in a specific way in multiple JSF pages, consider creating a page template for those pages. When you use the page template to build your pages, you can be sure that the pages are always consistent in structure and layout across the application. For details about creating and using page templates, see Section 19.3, "Using Page Templates," and Section 19.3.3, "How to Create JSF Pages Based on Page Templates."

  • Declarative components: The declarative components feature allows you to assemble existing, individual UI components into one composite, reusable component, which you then declaratively use in one or more pages. For example, if you are always inserting a group of components in multiple places, consider creating a composite declarative component that comprises the individual components, and then reusing that declarative component in multiple places throughout the application. Declarative components can also be used in page templates. For details about creating and using declarative components, see Section 19.4, "Using Declarative Components."

Tip:

If your application uses the ADF Controller and the ADF Model layer, then you can also use ADF regions. Regions used in conjunction with ADF bounded task flows, encapsulate business logic, process flow, and UI components all in one package, which can then be reused throughout the application. For complete information about creating and using ADF bounded task flows as regions, see the "Using Task Flows as Regions" chapter of the Oracle Fusion Middleware Fusion Developer's Guide for Oracle Application Development Framework.

Page templates, declarative components, and regions implement the javax.faces.component.NamingContainer interface. At runtime, in the pages that consume reusable content, the page templates, declarative components, or regions create component subtrees, which are then inserted into the consuming page's single, JSF component tree. Because the consuming page has its own naming container, when you add reusable content to a page, take extra care when using mechanisms such as partialTargets and findComponent(), as you will need to take into account the different naming containers for the different components that appear on the page. For more information about naming containers, see Section 3.5, "Locating a Client Component on a Page."

If you plan to include resources such as CSS or JavaScript, you can use the af:resource tag to add the resources to the page. If this tag is used in page templates and declarative components, the specified resources will be added to the consuming page during JSP execution. For more information, see Section 19.5, "Adding Resources to Pages."

19.2 Using Page Fragments

As you build web pages for an application, some pages may quickly become large and unmanageable. One possible way to simplify the process of building and maintaining complex pages is to use page fragments.

Large, complex pages broken down into several smaller page fragments are easier to maintain. Depending on how you design a page, the page fragments created for one page may be reused in other pages. For example, suppose different parts of several pages use the same form, then you might find it beneficial to create page fragments containing those components in the form, and reuse those page fragments in several pages. Deciding on how many page fragments to create for one or more complex pages depends on your application, the degree to which you wish to reuse portions of a page between multiple pages, and the desire to simplify complex pages.

Page fragments are incomplete JSF pages. A complete JSF page that uses ADF Faces must have the document tag enclosed within an f:view tag. The contents for the entire page are enclosed within the document tag. A page fragment, on the other hand, represents a portion of a complete page, and does not contain the f:view or document tags. The contents for the page fragment are simply enclosed within a jsp:root tag.

When you build a JSF page using page fragments, the page can use one or more page fragments that define different portions of the page. The same page fragment can be used more than once in a page, and in multiple pages.

Note:

The view parts of a page (fragments, declarative components, and the main page) all share the same request scope. This may result in a collision when you use the same fragment or declarative component multiple times on a page and the fragments or components share a backing bean. For more information about scopes, see Section 4.6, "Object Scope Lifecycles."

For example, the File Explorer application uses one main page (index.jspx) that includes the following page fragments:

  • popups.jspx: Contains all the popup code used in the application.

  • help.jspx: Contains the help content.

  • header.jspx: Contains the toolbars and menus for the application.

  • navigators.jspx: Contains the tree that displays the folder hierarchy of the application.

  • contentViews.jspx: Contains the content for the folder selected in the navigator pane.

Example 19-1 shows the abbreviated code for the included header.jspx page fragment. Note that it does not contain an f:view or document tag.

Example 19-1 header.jspx Page Fragment

<?xml version='1.0' encoding='UTF-8'?>
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" version="2.0"
          xmlns:af="http://xmlns.oracle.com/adf/faces/rich"
          xmlns:f="http://java.sun.com/jsf/core">
  <af:panelStretchLayout id="headerStretch">
    <f:facet name="center">
      <!-- By default, every toolbar is placed on a new row -->
      <af:toolbox id="headerToolbox"
                  binding="#{explorer.headerManager.headerToolbox}">
.
.
.
      </af:toolbox>
    </f:facet>
  </af:panelStretchLayout>
</jsp:root>

When you consume a page fragment in a JSF page, at the part of the page that will use the page fragment contents, you insert the jsp:include tag to include the desired page fragment file, as shown in Example 19-2, which is abbreviated code from the index.jspx page.

Example 19-2 File Explorer Index JSF Page Includes Fragments

<?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:af="http://xmlns.oracle.com/adf/faces/rich"
          xmlns:trh="http://myfaces.apache.org/trinidad/html">         
  <jsp:directive.page contentType="text/html;charset=utf-8"/>
  <f:view>
.
.
.
    <af:document id="fileExplorerDocument"
                 title="#{explorerBundle['global.branding_name']}">
      <af:form id="mainForm">
        <!-- Popup menu definition -->
        <jsp:include page="/fileExplorer/popups.jspx"/>
        <jsp:include page="/fileExplorer/help.jspx"/>
.
.
.
          <f:facet name="header">
            <af:group>
          <!-- The file explorer header with all the menus and toolbar buttons -->
              <jsp:include page="/fileExplorer/header.jspx"/>
            </af:group>
          </f:facet>
          <f:facet name="navigators">
            <af:group>
              <!-- The auxiliary area for navigating the file explorer -->
              <jsp:include page="/fileExplorer/navigators.jspx"/>
            </af:group>
          </f:facet>
          <f:facet name="contentViews">
            <af:group>
        <!-- Show the contents of the selected folder in the folders navigator -->
              <jsp:include page="/fileExplorer/contentViews.jspx"/>
            </af:group>
          </f:facet>
.
.
.
      </af:form>
    </af:document>
  </f:view>
</jsp:root>

When you modify a page fragment, the pages that consume the page fragment are automatically updated with the modifications. With pages built from page fragments, when you make layout changes, it is highly probable that modifying the page fragments alone is not sufficient; you may also have to modify every page that consumes the page fragments.

Note:

If the consuming page uses  ADF Model data binding, the included page fragment will use the binding container of the consuming page. Only page fragments created as part of ADF bounded task flows can have their own binding container. For information about ADF bounded task flows, see the "Getting Started With ADF Task Flows" chapter of the Oracle Fusion Middleware Fusion Developer's Guide for Oracle Application Development Framework.

Like complete JSF pages, page fragments can also be based on a page template, as shown in Example 19-3. For information about creating and applying page templates, see Section 19.3, "Using Page Templates," and Section 19.3.3, "How to Create JSF Pages Based on Page Templates."

Example 19-3 Page Fragment Based on a Template

<?xml version='1.0' encoding='windows-1252'?>
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" version="2.0"
          xmlns:af="http://xmlns.oracle.com/adf/faces/rich"
          xmlns:f="http://java.sun.com/jsf/core">
  <af:pageTemplate viewId="/someTemplateDefinition.jspx">
  .
  .
  .
  </af:pageTemplate>
</jsp:root>

19.2.1 How to Create a Page Fragment

Page fragments are just like any JSF page, except you do not use the f:view or document tags in page fragments. You can use the Create JSF Page Fragment wizard to create page fragments. When you create page fragments using the wizard, JDeveloper uses the extension .jsff for the page fragment files. If you do not use the wizard, you can use .jspx as the file extension (as the File Explorer application does); there is no special reason to use .jsff other than quick differentiation between complete JSF pages and page fragments when you are working in the Application Navigator in JDeveloper.

To create a page fragment:

  1. In the Application Navigator, right-click the folder where you wish to create and store page fragments and choose New.

  2. In the Categories tree, select the JSF node, in the Items pane select JSF Page Fragment, and click OK.

  3. Enter a name for the page fragment file.

  4. Accept the default directory for the page fragment, or choose a new location.

    By default, JDeveloper saves page fragments in the project's /public_html directory in the file system. For example, you could change the default directory to /public_html/fragments.

  5. You can have your fragment pre-designed for you by using either a template or a Quick Start Layout.

    • If you want to create a page fragment based on a page template, select the Page Template radio button and then select a template name from the dropdown list. For more information about using page templates, see Section 19.3.3, "How to Create JSF Pages Based on Page Templates."

    • If you want to use a Quick Start Layout, select the Quick Start Layout radio button and then click Browse to select the layout you want your fragment to use. Quick Start Layouts provide the correctly configured layout components need to achieve specific behavior and look. For more information, see Section 8.2.3, "Using Quick Start Layouts."

    When the page fragment creation is complete, JDeveloper displays the page fragment file in the visual editor.

  6. To define the page fragment contents, drag and drop the desired components from the Component Palette onto the page.

    You can use any ADF Faces or standard JSF component, for example table, panelHeader, or f:facet.

Example 19-4 shows an example of a page fragment that contains a menu component.

Example 19-4 Page Fragment Sample

<?xml version='1.0' encoding='windows-1252'?>
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" version="2.0"
          xmlns:af="http://xmlns.oracle.com/adf/faces/rich">
  <!-- page fragment contents start here -->
  <af:menu id="viewMenu"
    <af:group>
      <af:commandMenuItem type="check" text="Folders"/>
      <af:commandMenuItem type="check" text="Search"/>
    </af:group>
    <af:group>
      <af:commandMenuItem type="radio" text="Table"/>
      <af:commandMenuItem type="radio" text="Tree Table"/>
      <af:commandMenuItem type="radio" text="List"/>
    </af:group>
    <af:commandMenuItem text="Refresh"/>
  </menu>
</jsp:root>

19.2.2 What Happens When You Create a Page Fragment

In JDeveloper, because page fragment files use a different file extension from regular JSF pages, configuration entries are added to the web.xml file for recognizing and interpreting .jsff files in the application. Example 19-5 shows the web.xml configuration entries needed for .jsff files, which JDeveloper adds for you when you first create a page fragment using the wizard.

Example 19-5 Entries in web.xml for Recognizing and Interpreting .jsff Files

<jsp-config>
  <jsp-property-group>
    <url-pattern>*.jsff</url-pattern>
    <is-xml>true</is-xml>
  </jsp-property-group>
</jsp-config>

By specifying the url-pattern subelement to *.jsff and setting the is-xml subelement to true in a jsp-property-group element, the application will recognize that files with extension .jsff are actually JSP documents, and thus must be interpreted as XML documents.

19.2.3 How to Use a Page Fragment in a JSF Page

To consume a page fragment in a JSF page, add the page using either the Component Palette or the Application Navigator.

19.2.3.1 Adding a Page Fragment Using the Component Palette

You can use the jsp:include tag to include the desired page fragment file

To add a page fragment using the Component Palette:

  1. In the Component Palette, use the dropdown menu to choose JSP.

  2. Add a jsp:include tag by dragging and dropping Include from the Component Palette.

  3. In the Insert Include dialog, use the dropdown list to select the JSF page to include. Optionally, select whether or not to flush the buffer before the page is included. For more information, click Help in the dialog.

19.2.3.2 Adding a Page Fragment Using the Application Navigator

You can drag and drop the page fragment directly onto the page.

To add a page fragment using the Application Navigator:

  1. In the Application Navigator, drag and drop the page fragment onto the page.

  2. In the Confirm Add Subview Element dialog, click Yes.

19.2.4 What Happens at Runtime: Resolving Page Fragments

When the page that contains the included page(s) is executed, the jsp:include tag evaluates the view ID during JSF tree component build time and dynamically adds the content to the parent page at the location of the jsp:include tag. The fragment becomes part of the parent page after the component tree is built.

19.3 Using Page Templates

Page templates let you define entire page layouts, including values for certain attributes of the page. When pages are created using a template, they all inherit the defined layout. When you make layout modifications to the template, all pages that consume the template will automatically reflect the layout changes. You can either create the layout of your template yourself, or you can use one of the many quick layout designs. These predefined layouts automatically insert and configure the correct components required to implement the layout look and behavior you want. For example, you may want one column's width to be locked, while another column stretches to fill available browser space. Figure 19-1 shows the quick layouts available for a two-column layout with the second column split between two panes. For more information about the layout components, see Chapter 8, "Organizing Content on Web Pages."

Figure 19-1 Quick Layouts

Quick Layouts speed design

To use page templates in an application, you first create a page template definition. Page template definitions must be JSF documents written in XML syntax (with the file extension of .jspx) because page templates embed XML content. In contrast to regular JSF pages where all components on the page must be enclosed within the f:view tag, page template definitions cannot contain an f:view tag and must have pageTemplateDef as the root tag. Either the template or the page that uses the template must contain the document tag, but they cannot both contain the tag (by default, JDeveloper adds the document tag to the consuming page).

A page template can have fixed content areas and dynamic content areas. For example, if a Help button should always be located at the top right-hand corner of pages, you could define such a button in the template layout, and when page authors use the template to build their pages, they do not have to add and configure a Help button. Dynamic content areas, on the other hand, are areas of the template where page authors can add contents within defined facets of the template or set property values that are specific to the type of pages they are building.

The entire description of a page template is defined within the pageTemplateDef tag, which has two sections. One section is within the xmlContent tag, which contains all the page template component metadata that describes the template's supported content areas (defined by facets), and available properties (defined as attributes). The second section (anything outside of the xmlContent tag) is where all the components that make up the actual page layout of the template are defined. The components in the layout section provide a JSF component subtree that is used to render the contents of the page template.

Facets act as placeholders for content on a page. In a page that consumes a template, page authors can insert content for the template only in named facets that have already been defined. This means that when you design a page template, you must define all possible facets within the xmlContent tag, using a facet element for each named facet. In the layout section of a page template definition, as you build the template layout using various components, you use the facetRef tag to reference the named facets within those components where content can eventually be inserted into the template by page authors.

For example, the fileExplorerTemplate template contains a facet for copyright information and another facet for application information, as shown in Example 19-6.

Example 19-6 Facet Definition in a Template

<facet>  <description> 
    <![CDATA[Area to put a commandLink to more information 
             about the application.]]>
  </description>
  <facet-name>appAbout</facet-name>
</facet>
<facet>
  <description>
    <![CDATA[The copyright region of the page.  If present, this area
             typically contains an outputText component with the copyright
             information.]]>
  </description>
  <facet-name>appCopyright</facet-name>
</facet>

In the layout section of the template as shown in Example 19-7, a panelGroupLayout component contains a table whose cell contains a reference to the appCopyright facet and another facet contains a reference to the appAbout facet. This is where a page developer will be allowed to place that content.

Example 19-7 Facet References in a Page Template

<af:panelGroupLayout layout="vertical">
  <afh:tableLayout width="100%">
    <afh:rowLayout>
      <afh:cellFormat>
        <af:facetRef facetName="appCopyright"/>
      </afh:cellFormat>
    </afh:rowLayout>
  </afh:tableLayout>
  <af:facetRef facetName="appAbout"/>
</af:panelGroupLayout>

Note:

To avoid component ID collisions at runtime, each named facet can be referenced only once in the layout section of the page template definition. That is, you cannot use multiple facetRef tags referencing the same facetName value in the same template definition.

While the pageTemplateDef tag describes all the information and components needed in a page template definition, the JSF pages that consume a page template use the pageTemplate tag to reference the page template definition. Example 19-7 shows how the index.jspx page references the fileExplorerTemplate template, provides values for the template's attributes, and places content within the template's facet definitions.

At design time, page developers using the template can insert content into the appCopyright facet, using the f:facet tag, as shown in Example 19-8

Example 19-8 Using Page Templates Facets in a JSF Page

<af:pageTemplate id="fe"
                 viewId="/fileExplorer/templates/fileExplorerTemplate.jspx">
  <f:attribute name="documentTitle" 
               value="#{explorerBundle['global.branding_name']}"/>
  <f:attribute name="headerSize" value="70"/>
  <f:attribute name="navigatorsSize" value="370"/>
.
.
.
  <f:facet name="appCopyright">
    <!-- Copyright info about File Explorer demo -->
    <af:outputFormatted value="#{explorerBundle['about.copyright']}"/>
  </f:facet>
    .
    .
    .
</af:pageTemplate>

At runtime, the inserted content is displayed in the right location on the page, as indicated by af:facetRef facetName="appCopyright" in the template definition.

Note:

You cannot run a page template as a run target in JDeveloper. You can run the page that uses the page template.

Page template attributes specify the component properties (for example, headerGlobalSize) that can be set or modified in the template. While facet element information is used to specify where in a template content can be inserted, attribute element information is used to specify what page attributes are available for passing into a template, and where in the template those attributes can be used to set or modify template properties.

For the page template to reference its own attributes, the pageTemplateDef tag must have a var attribute, which contains an EL variable name for referencing each attribute defined in the template. For example, in the fileExplorerTemplate template, the value of var on the pageTemplateDef tag is set to attrs. Then in the layout section of the template, an EL expression such as #{attrs.someAttributeName} is used in those component attributes where page authors are allowed to specify their own values or modify default values.

For example, the fileExplorerTemplate template definition defines an attribute for the header size, which has a default int value of 100 pixels as shown in Example 19-9.

Example 19-9 Page Template AttributeDefinition

<attribute>
  <description>
    Specifies the number of pixels tall that the global header content should 
    consume.
  </description>
  <attribute-name>headerGlobalSize</attribute-name>
  <attribute-class>int</attribute-class>
  <default-value>100</default-value>
</attribute>

In the layout section of the template, the splitterPosition attribute of the panelSplitter component references the headerGlobalSize attribute in the EL expression #{attrs.headerGlobalSize}, as shown in the following code:

<af:panelSplitter splitterPosition="#{attrs.headerGlobalSize}" ../>

When page authors use the template, they can modify the headerGlobalSize value using f:attribute, as shown in the following code:

<af:pageTemplate ..>
  <f:attribute name="headerGlobalSize" value="50"/>
  .
  .
  .
</af:pageTemplate>

At runtime, the specified attribute value is substituted into the appropriate part of the template, as indicated by the EL expression that bears the attribute name.

Tip:

If you define a resource bundle in a page template, the pages that consume the template will also be able to use the resource bundle. For information about using resource bundles, see Section 21.3, "Manually Defining Resource Bundles and Locales."

For a simple page template, it is probably sufficient to place all the components for the entire layout section into the page template definition file. For a more complex page template, you can certainly break the layout section into several smaller fragment files for easier maintenance, and use jsp:include tags to include and connect the various fragment files.

When you break the layout section of a page template into several smaller fragment files, all the page template component metadata must be contained within the xmlContent tag in the main page template definition file. There can be only one xmlContent tag within a pageTemplateDef tag. You cannot have page template component metadata in the fragment files; fragment files can contain portions of the page template layout components only.

Note:

You cannot nest page templates inside other page templates.

If your template requires resources such as custom styles defined in CSS or JavaScript, then you need to include these on the consuming page, using the af:resource tag. For more information, see Section 19.5, "Adding Resources to Pages."

19.3.1 How to Create a Page Template

JDeveloper simplifies creating page template definitions by providing the Create JSF Page Template wizard, which lets you add named facets and attributes declaratively to create the template component metadata section of a template. In addition to generating the metadata code for you, JDeveloper also creates and modifies a pagetemplate-metadata.xml file that keeps track of all the page templates you create in a project.

Performance Tip:

Because page templates may be present in every application page, templates should be optimized so that common overhead is avoided. One example of overhead is round corners, for example on boxes, which are quite expensive. Adding them to the template will add overhead to every page.

To create a page template definition:

  1. In the Application Navigator, right-click the folder where you wish to create and store page templates and choose New.

  2. In the Categories tree, select the JSF node, in the Items pane select JSF Page Template, and click OK.

  3. Enter a file name for the page template definition. Page template definitions must be XML documents (with file extension .jspx) because they embed XML content.

    Performance Tip:

    Avoid long names because they can have an impact on server-side, network traffic, and client processing.
  4. Accept the directory name for the template definition, or choose a new location.

  5. Enter a Page Template name for the page template definition.

  6. If you want to use one of the predefined quick layouts, select Use a Quick Start Layout and click Browse to select the one you want to use.

  7. To add named facets, click the Facet Definitions tab and click the Add icon.

    Facets are predefined areas on a page template where content can eventually be inserted when building pages using the template. Each facet must have a unique name. For example, you could define a facet called main for the main content area of the page, and a facet called branding for the branding area of the page.

  8. To add attributes, click the Attributes tab and click the Add icon.

    Attributes are UI component attributes that can be passed into a page when building pages using the template. Each attribute must have a name and class type. Note that whatever consumes the attribute (for example an attribute on a component that you configure in Step 12) must be able to accept that type. You can assign default values, and you can specify that the values are mandatory by selecting the Required checkbox.

  9. If the page template contents use ADF Model data bindings, select the Create Associated ADFm Page Definition checkbox, and click Model Parameters to add one or more model parameters. For information about using model parameters and ADF Model data bindings, see the "Using Page Templates" section of the Oracle Fusion Middleware Fusion Developer's Guide for Oracle Application Development Framework.

    Once you complete the wizard, JDeveloper displays the page template definition file in the visual editor. Example 19-10 shows the code JDeveloper adds for you when you use the wizard to define the metadata for a page template definition. You can view this code in the source editor.

    Tip:

    Once a template is created, you can add facets and attributes by selecting the pageTemplateDef tag in the Structure window and using the Property Inspector.

    Note:

    When you change or delete any facet name or attribute name in the template component metadata, you have to manually change or delete the facet or attribute name referenced in the layout section of the template definition, as well as the JSF pages that consume the template.

    Example 19-10 Component Metadata in Page Template Definition

    <af:pageTemplateDef var="attrs">
      <af:xmlContent>
        <component xmlns="http://xmlns.oracle.com/adf/faces/rich/component">
          <display-name>sampleTemplateDef1</display-name>
          <facet>
            <facet-name>main</facet-name>
          </facet>
          .
          .
          .
          <attribute>
            <attribute-name>Title</attribute-name>
            <attribute-class>java.lang.String</attribute-class>
            <default-value>Replace title here</default-value>
            <required>true</required>
          </attribute>
          .
          .
          .
        </component>
      </af:xmlContent>
      .
      .
      .
    </af:pageTemplateDef>
    
  10. Drag a component from the Component Palette and drop it onto the page in the visual editor.

    In the layout section of a page template definition (or in fragment files that contain a portion of the layout section), you cannot use the f:view tag, because it is already used in the JSF pages that consume page templates.

    Best Practice Tip:

    You should not use the document or form tags in the template. While theoretically, template definitions can use the document and form tags, doing so means the consuming page cannot. Because page templates can be used for page fragments, which in turn will be used by another page, it is likely that the consuming page will contain these tags.

    You can add any number of components to the layout section. If you did not choose to use one of the quick start layouts, then typically, you would add a panel component such as panelStretchLayout or panelGroupLayout, and then add the components that define the layout into the panel component. For more information, see Chapter 8, "Organizing Content on Web Pages."

    Declarative components and databound components may be used in the layout section. For information about using declarative components, see Section 19.4, "Using Declarative Components." For information about using databound components in page templates, see the "Using Page Templates" section of the Oracle Fusion Middleware Fusion Developer's Guide for Oracle Application Development Framework.

  11. Within those components (in the layout section) where content can eventually be inserted by page authors using the template, drag FacetRef from the Component Palette and drop it in the desired location on the page.

    For example, if you have defined a main facet for the main content area on a page template, you might add the facetRef tag as a child in the center facet of panelStretchLayout component to reference the main facet. At design time, when the page author drops content into the main facet, the content is placed in the correct location on the page as defined in the template.

    When you use the facetRef tag to reference the appropriate named facet, JDeveloper displays the Insert FacetRef dialog. In that dialog, select a facet name from the dropdown list, or enter a facet name. If you enter a facet name that is not already defined in the component metadata of the page template definition file, JDeveloper automatically adds an entry for the new facet definition in the component metadata within the xmlContent tag.

    Note:

    Each facet can be referenced only once in the layout section of the page template definition. That is, you cannot use multiple facetRef tags referencing the same facetName value in the same template definition.
  12. To specify where attributes should be used in the page template, use the page template's var attribute value to reference the relevant attributes on the appropriate components in the layout section.

    The var attribute of the pageTemplateDef tag specifies the EL variable name that is used to access the page template's own attributes. As shown in Example 19-10, the default value of var used by JDeveloper is attrs.

    For example, if you have defined a title attribute and added the panelHeader component, you might use the EL expression #{attrs.title} in the text value of the panelHeader component, as shown in the following code, to reference the value of title:

    <af:panelHeader text="#{attrs.title}">
    
  13. To include another file in the template layout, use the jsp:include tag wrapped inside the subview tag to reference a fragment file, as shown in the following code:

    <f:subview id="secondaryDecoration">
      <jsp:include page="fileExplorerSecondaryDecoration.jspx"/>
    </f:subview>
    

    The included fragment file must also be an XML document, containing only jsp:root at the top of the hierarchy. For more information about using fragments, see Section 19.2.3, "How to Use a Page Fragment in a JSF Page."

    By creating a few fragment files for the components that define the template layout, and then including the fragment files in the page template definition, you can split up an otherwise large template file into smaller files for easier maintenance.

19.3.2 What Happens When You Create a Page Template

Note:

If components in your page template use ADF Model data binding, or if you chose to associate an ADF page definition when you created the template, JDeveloper automatically creates files and folders related to ADF Model. For information about the files used with page templates and ADF Model data binding, the "Using Page Templates" section of the Oracle Fusion Middleware Fusion Developer's Guide for Oracle Application Development Framework.

The first time you use the wizard to create a JSF page template in a project, JDeveloper automatically creates the pagetemplate-metadata.xml file, which is placed in the /ViewController/src/META-INF directory in the file system.

For each page template that you define using the wizard, JDeveloper creates a page template definition file (for example, sampleTemplateDef1.jspx), and adds an entry to the pagetemplate-metadata.xml file. Example 19-11 shows an example of the pagetemplate-metadata.xml file.

Example 19-11 Sample pagetemplate-metadata.xml File

<pageTemplateDefs xmlns="http://xmlns.oracle.com/adf/faces/rich/pagetemplate">
  <pagetemplate-jsp-ui-def>/sampleTemplateDef1.jspx</pagetemplate-jsp-ui-def>
  <pagetemplate-jsp-ui-def>/sampleTemplateDef2.jspx</pagetemplate-jsp-ui-def>
</pageTemplateDefs>

Note:

When you rename or delete a page template in the Application Navigator, JDeveloper renames or deletes the page template definition file in the file system, but you must manually change or delete the page template entry in the pagetemplate-metadata.xml file, and update or remove any JSF pages that use the template.

The pagetemplate-metadata.xml file contains the names and paths of all the page templates that you create in a project. This file is used to determine which page templates are available when you use a wizard to create template-based JSF pages, and when you deploy a project containing page template definitions.

19.3.3 How to Create JSF Pages Based on Page Templates

Typically, you create JSF pages in the same project where page template definitions are created and stored. If the page templates are not in the same project as where you are going to create template-based pages, first deploy the page templates project to an ADF Library JAR. For information about deploying a project, see the "Reusing Application Components" chapter of the Oracle Fusion Middleware Fusion Developer's Guide for Oracle Application Development Framework. Deploying a page template project also allows you to share page templates with other developers working on the application.

Note:

If the template uses jsp:include tags, then it cannot be deployed to an ADF Library to be reused in other applications.

You can use page templates to build JSF pages or page fragments. If you modify the layout section of a page template later, all pages or page fragments that use the template are automatically updated with the layout changes.

In the page that consumes a template, you can add content before and after the pageTemplate tag. In general, you would use only one pageTemplate tag in a page, but there are no restrictions for using more than one.

JDeveloper simplifies the creation of JSF pages based on page templates by providing a template selection option in the Create JSF Page or Create JSF Page Fragment wizard.

To create a JSF page or page fragment based on a page template:

  1. Follow the instructions in Section 2.4.1, "How to Create JSF JSP Pages" to open the Create JSF Page dialog. In the dialog, select a page template to use from the Use Page Template dropdown list.

    Tip:

    Only page templates that have been created using the template wizard in JDeveloper are available for selection. If the Use Page Template dropdown list is disabled, this means no page templates are available in the project where you are creating new pages.

    By default, JDeveloper displays the new page or page fragment in the visual editor. The facets defined in the page template appear as named boxes in the visual editor. If the page template contains any default values, you should see the values in the Property Inspector, and if the default values have some visual representation (for example, size), that will be reflected in the visual editor, along with any content that is rendered by components defined in the layout section of the page template definition.

  2. In the Structure window, expand jsp:root until you see af:pageTemplate (which should be under af:form).

    Within the form tag, you can drop content before and after the pageTemplate tag.

  3. Add components by dragging and dropping components from the Component Palette in the facets of the template. In the Structure window, within af:pageTemplate, the facets (for example, f:facet - main) that have been predefined in the component metadata section of the page template definition are shown.

    The type of components you can drop into a facet may be dependent on the location of the facetRef tag in the page template definition. For example, if you've defined a facetRef tag to be inside a table component in the page template definition, then only column components can be dropped into the facet because the table component accepts only column components as children.

    Tip:

    The content you drop into the template facets may contain ADF Model data binding. In other words, you can drag and drop items from the Data Controls panel. For more information about using ADF Model data binding, see Oracle Fusion Middleware Fusion Developer's Guide for Oracle Application Development Framework.
  4. In the Structure window, select af:pageTemplate. Then, in the Property Inspector, you can see all the attributes that are predefined in the page template definition. Predefined attributes might have default values.

    You can assign static values to the predefined attributes, or you can use EL expressions (for example, #{myBean.somevalue}). When you enter a value for an attribute, JDeveloper adds the f:attribute tag to the code, and replaces the attribute's default value (if any) with the value you assign (see Example 19-12).

    At runtime, the default or assigned attribute value is used or displayed in the appropriate part of the template, as specified in the page template definition by the EL expression that bears the name of the attribute (such as #{attrs.someAttributeName}).

    Note:

    In addition to predefined template definition attributes, the Property Inspector also shows other attributes of the pageTemplate tag such as Id, Value, and ViewId.

    The ViewId attribute of the pageTemplate tag specifies the page template definition file to use in the consuming page at runtime. JDeveloper automatically assigns the ViewId attribute with the appropriate value when you use the wizard to create a template-based JSF page. The ViewId attribute value cannot be removed, otherwise a runtime error will occur, and the parts of the page that are based on the template will not render.

  5. To include resources, such as CSS or JavaScript, you need to use the af:resource tag. For more information, see Section 19.5, "Adding Resources to Pages."

19.3.4 What Happens When You Use a Template to Create a Page

When you create a page using a template, JDeveloper inserts the pageTemplate tag, which references the page template definition, as shown in Example 19-12. Any components added inside the template's facets use the f:facet tag to reference the facet. Any attribute values you specified are shown in the f:attribute tag.

Example 19-12 JSF Page that References a Page Template

<?xml version='1.0' encoding='windows-1252'?>
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" version="2.0"
          xmlns:f="http://java.sun.com/jsf/core"
          xmlns:af="http://xmlns.oracle.com/adf/faces/rich">
  <jsp:directive.page contentType="text/html;charset=windows-1252"/>
  <f:view>
    <af:document>
      <af:form>
        .
        .
        .
        <af:pageTemplate viewId="/sampleTemplateDef1.jspx" id="template1">
          <f:attribute name="title" value="Some Value"/>
          <f:facet name="main">
            <!-- add contents here -->
          </f:facet>
        </af:pageTemplate>
        .
        .
        .
      </af:form>
    </af:document>
  </f:view>
</jsp:root>

19.3.5 What Happens at Runtime: How Page Templates Are Resolved

When a JSF page that consumes a page template is executed:

  • The pageTemplate component in the consuming page, using the viewId attribute (for example, <af:pageTemplate viewId="/sampleTemplateDef1.jspx"/>), locates the page template definition file that contains the template component metadata and layout.

  • The component subtree defined in the layout section of the pageTemplateDef tag is instantiated and inserted into the consuming page's component tree at the location identified by the pageTemplate tag in the page.

  • The consuming page passes facet contents into the template using the facet tag. The facet contents of each facet tag are inserted into the appropriate location on the template as specified by the corresponding facetRef tag in the layout section of the pageTemplateDef tag.

  • The consuming page passes values into the template by using the attribute tag. The pageTemplateDef tag sets the value of the var attribute so that the pageTemplate tag can internally reference its own parameters. The pageTemplate tag just sets the parameters; the runtime maps those parameters into the attributes defined in the pageTemplateDef tag.

  • Using template component metadata, the pageTemplate tag applies any default values to its attributes and checks for required values.

Note:

Page templates are processed during JSP execution, not during JSF processing (that is, component tree creation). This means that fragments built from page templates cannot be used within tags that require the component tree creation. For example, you could not include a fragment based on a template within an iterator tag and expect it to be included in a loop.

For information about what happens when the page template uses ADF Model data binding, see the "Using Page Templates" section of the Oracle Fusion Middleware Fusion Developer's Guide for Oracle Application Development Framework.

19.3.6 What You May Need to Know About Page Templates and Naming Containers

The pageTemplate component acts as a naming container for all content in the template (whether it is direct content in the template definition, or fragment content included using the jsp:include action). When working with client-side events in template-based pages, you must include the template's ID when using code to locate a component. For more details, see Section 5.3.7, "What You May Need to Know About Using Naming Containers."

19.4 Using Declarative Components

Declarative components are reusable, composite UI components that are made up of other existing ADF Faces components. Suppose you are reusing the same components consistently in multiple circumstances. Instead of copying and pasting the commonly used UI elements repeatedly, you can define a declarative component that comprises those components, and then reuse that composite declarative component in multiple places or pages.

Note:

The view parts of a page (fragments, declarative components, and the main page) all share the same request scope. This may result in a collision when you use the same fragment or declarative component multiple times on a page, and when they share a backing bean. For more information about scopes, see Section 4.6, "Object Scope Lifecycles."

To use declarative components in an application, you first create an XML-based declarative component definition, which is a JSF document written in XML syntax (with a file extension of .jspx). Declarative component JSF files do not contain the f:view and document tags, and they must have componentDef as the root tag.

The entire description of a declarative component is defined within two sections. One section is xmlContent, which contains all the page template component metadata that describes the declarative component's supported content areas. A declarative component's metadata includes the following:

  • Facets: Facets act as placeholders for the content that will eventually be placed in the individual components that make up the declarative component. Each component references one facet. When page designers use a declarative component, they insert content into the facet, which in turn, allows the content to be inserted into the component.

    Tip:

    Facets are the only area within a declarative component that can contain content. That is, when used on a JSF page, a declarative component may not have any children. Create facets for all areas where content may be needed.
  • Attributes: You define attributes whose values can be used to populate attributes on the individual components. For example, if your declarative component uses a panelHeader component, you may decide to create an attribute named Title. You may then design the declarative component so that the value of the Title attribute is used as the value for the text attribute of the panelHeader component. You can provide default values for attributes that the user can then override.

    Tip:

    Because users of a declarative component will not be able to directly set attributes on the individual components, you must be sure to create attributes for all attributes that you want users to be able to set or override the default value.

    Additionally, if you want the declarative component to be able to use client-side attributes (for example, attributeDragSource), you must create that attribute and be sure to include it as a child to the appropriate component used in the declarative component. For more information, see Section 19.4.1, "How to Create a Declarative Component."

  • Methods: You can define a method to which you can bind a property on one of the included components. For example, if your declarative component contains a button, you can declare a method name and signature and then bind the actionListener attribute to the declared method. When page developers use the declarative component, they rebind to a method on a managed bean that contains the logic required by the component.

    For example, say your declarative component contains a button that you knew always had to invoke an actionEvent method. You might create a declarative method named method1 that used the signature void method(javax.faces.event.ActionEvent). You might then bind the actionListener attribute on the button to the declared method. When page developers use the declarative component, JDeveloper will ask them to provide a method on a backing bean that uses the same signature.

  • Tag library: All declarative components must be contained within a tag library that you import into the applications that will use them.

The second section (anything outside of the xmlContent tag) is where all the components that make up the declarative component are defined. Each component contains a reference back to the facet that will be used to add content to the component.

To use declarative components in a project, you first must deploy the library that contains the declarative component as an ADF Library. You can then add the deployed ADF Library JAR to the project's properties, which automatically inserts the JSP tag library or libraries into the project's properties. Doing so allows the component(s) to be displayed in the Component Palette so that you can drag and drop them onto a JSF page.

For example, say you want to create a declarative component that uses a panelBox component. In the panelBox component's toolbar, you want to include three buttons that can be used to invoke actionEvent methods on a backing bean. To do this, create the following:

  • One facet named Content to hold the content of the panelBox component.

  • One attribute named Title to determine the text to display as the panelBox component's title.

  • Three attributes (one for each button, named buttonText1, buttonText2, and buttonText3) to determine the text to display on each button.

  • Three attributes (one for each button, named display1, display2, display3) to determine whether or not the button will render, because you do not expect all three buttons will be needed every time the component is used.

  • Three declarative methods (one for each button, named method1, method2, and method3) that each use the actionEvent method signature.

  • One panelBox component whose text attribute is bound to the created Title attribute, and references the Content facet.

  • Three toolbarButton components. The text attribute for each would be bound to the corresponding buttonText attribute, the render attribute would be bound to the corresponding display attribute, and the actionListener attribute would be bound to the corresponding method name.

Figure 19-2 shows how such a declarative component would look in the visual editor.

Figure 19-2 Declarative Component in the Visual Editor

Visual editor shows the individual components

When a page developer drops a declarative component that contains required attributes or methods onto the page, a dialog opens asking for values.

If the developer set values where only the first two buttons would render, and then added a panelGroupLayout component with output text, the page would render as shown in Figure 19-3.

Figure 19-3 Displayed Declarative Component

Declarative component at runtime

Note:

You cannot use fragments or ADF databound components in the component layout of a declarative component. If you think some of the components will need to be bound to the ADF Model layer, then create attributes for those component attributes that need to be bound. The user of the declarative component can then manually bind those attributes to the ADF Model layer.

Additionally, because declarative components are delivered in external JAR files, the components cannot use the jsp:include tag because it will not be able to find the referenced files.

If your declarative component requires resources such as custom styles defined in CSS or JavaScript, then you need to include these using the af:resource tag on the consuming page. For more information, see Section 19.5, "Adding Resources to Pages."

19.4.1 How to Create a Declarative Component

JDeveloper simplifies creating declarative component definitions by providing the Create JSF Declarative Component wizard, which lets you create facets, and define attributes and methods for the declarative component. The wizard also creates metadata in the component-extension tile that describes tag library information for the declarative component. The tag library metadata is used to create the JSP tag library for the declarative component.

First you add the template component metadata for facets and attributes inside the xmlContent section of the componentDef tag. After you have added all the necessary component metadata for facets and attributes, then you add the components that define the actual layout of the declarative component in the section outside of the xmlContent section.

Best Practice Tip:

Because the tag library definition (TLD) for the declarative component must be generated before the component can be used, the component must be deployed to a JAR file before it can be consumed. It is best to create an application that contains only your declarative components. You can then deploy all the declarative components in a single library for use in multiple applications.

To create a declarative component definition:

  1. In the Application Navigator, right-click the folder where you wish to create and store declarative components and choose New.

  2. In the Categories tree, select the JSF node, in the Items pane select JSF Declarative Component, and click OK.

  3. Enter a name and file name for the declarative component.

    The name you specify will be used as the display name of the declarative component in the Component Palette, as well as the name of the Java class generated for the component tag. Only alphanumeric characters are allowed in the name for the declarative component, for example, SampleName or SampleName1.

    The file name is the name of the declarative component definition file (for example, componentDef1.jspx). By default, JDeveloper uses .jspx as the file extension because declarative component definition files must be XML documents.

  4. Accept the default directory name for the declarative component, or choose a new location.

    By default, JDeveloper saves declarative component definitions in the /ViewController/public_html directory in the file system. For example, you could save all declarative component definitions in the /View Controller/public_html/declcomps directory.

  5. Enter a package name (for example, dcomponent1). JDeveloper uses the package name when creating the Java class for the declarative component.

  6. Select a tag library to contain the new declarative component. If no tag library exists, or if you wish to create a new one, click Add Tag Library, and do the following to create metadata for the tag library:

    1. Enter a name for the JSP tag library to contain the declarative component (for example, dcompLib1).

    2. Enter the URI for the tag library (for example, /dcomponentLib1).

    3. Enter a prefix to use for the tag library (for example, dc).

  7. If you want to be able to add custom logic to your declarative component, select the Use Custom Component Class checkbox and enter a class name.

  8. To add named facets, click the Facet Definitions tab and click the Add icon.

    Facets in a declarative component are predefined areas where content can eventually be inserted. The components you use to create the declarative component will reference the facets. When page developers use the declarative components, they will place content into the facets, which in turn will allow the content to be placed into the individual components. Each facet must have a unique name. For example, your declarative component has a panelBox component, you could define a facet named box-main for the content area of the panelBox component.

  9. To add attributes, click Attributes and click Add.

    Attributes are UI component attributes that can be passed into a declarative component. Each attribute must have a name and class type. Possible class types to use are: java.lang.String, int, boolean, and float. You can assign default values, and you can specify that the values are mandatory by selecting the Required checkbox.

    Tip:

    You must create attributes for any attributes on the included components for which you want users to be able to set or change values.

    Remember to also add attributes for any tags you may need to add to support functionality of the component, for example values required by the attributeDragSource tag used for drag and drop functionality.

  10. To add declarative methods, click the Methods tab and click the Add icon.

    Declarative methods allow you to bind command component actions or action listeners to method signatures, which will later resolve to actual methods of the same signature on backing beans for the page on which the components are used. You can click the ellipses button to open the Method Signature dialog, which allows you to search for and build your signature.

    When you complete the dialog, JDeveloper displays the declarative component definition file in the visual editor.

    Tip:

    Once a declarative component is created, you can add facets and attributes by selecting the componentDef tag in the Structure window, and using the Property Inspector.
  11. Drag a component from the Component Palette and drop it as a child to the componentDef tag in the Structure window.

    Suppose you dropped a panelBox component. In the Structure window, JDeveloper adds the component after the xmlContent tag. It does not matter where you place the components for layout, before or after the xmlContent tag, but it is good practice to be consistent.

    You can use any number of components in the component layout of a declarative component. Typically, you would add a component such as panelFormLayout or panelGroupLayout, and then add the components that define the layout into the panel component.

    Note:

    You cannot use fragments or ADF databound components in the component layout of a declarative component. If you think some of the components will need to be bound to the ADF Model layer, then create attributes for those component attributes. The user of the declarative component can then manually bind those attributes to the ADF Model layer. For more information about using the ADF Model layer, see the "Using ADF Model in a Fusion Web Application" chapter in the Oracle Fusion Middleware Fusion Developer's Guide for Oracle Application Development Framework.

    Additionally, because declarative components are delivered in external JAR files, the components cannot use the jsp:include tag because it will not be able to find the referenced files.

  12. Within those components (in the layout section) where content can eventually be inserted by page authors using the component, use the facetRef tag to reference the appropriate named facet.

    For example, if you have defined a content facet for the main content area, you might add the facetRef tag as a child in the panelBox component to reference the content facet. At design time, when the page developer drops components into the content facet, the components are placed in the panelBox component.

    When you drag FacetRef from the Component Palette and drop it in the desired location on the page, JDeveloper displays the Insert FacetRef dialog. In that dialog, select a facet name from the dropdown list, or enter a facet name. If you enter a facet name that is not already defined in the component metadata of the definition file, JDeveloper automatically adds an entry for the new facet definition in the component metadata within the xmlContent tag.

    Note:

    Each facet can be referenced only once. That is, you cannot use multiple facetRef tags referencing the same facetName value in the same declarative component definition.
  13. To specify where attributes should be used in the declarative component, use the Property Inspector and the Expression Builder to bind component attribute values to the created attributes.

    For example, if you have defined a title attribute and added a panelBox as a component, you might use the dropdown menu next to the text attribute in the Property Inspector to open the Expression Builder, as shown in Figure 19-4.

    Figure 19-4 Opening the Expression Builder for an Attribute in the Property Inspector

    Expression builder is accessible from the PI

    In the Expression Builder, you can expand the JSP Objects > attrs node to select the created attribute that should be used for the value of the attribute in the Property Inspector. For example, Figure 19-5 shows the title attribute selected in the Expression Builder. Click the Insert Into Expression button and then click OK to add the expression as the value for the attribute.

    Figure 19-5 Expression Builder Displays Created Attributes

    Expression builder
  14. To specify the methods that command buttons in the declarative component should invoke, use the dropdown menu next to that component's actionListener attribute and choose Edit to open the Edit Property dialog. This dialog allows you to choose one of the declarative methods you created for the declarative component.

    In the dialog, select Declarative Component Methods, select the declarative method from the dropdown list, and click OK.

19.4.2 What Happens When You Create a Declarative Component

When you first use the Create JSF Declarative Component wizard, JDeveloper creates the metadata file using the name you entered in the wizard. The entire definition for the component is contained in the componentDef tag. This tag uses two attributes. The first is var, which is a variable used by the individual components to access the attribute values. By default, the value of var is attrs. The second attribute is componentVar, which is a variable used by the individual components to access the methods. By default the value of componentVar is component.

The metadata describing the facets, attributes, and methods is contained in the xmlContent tag. Facet information is contained within the facet tag, attribute information is contained within the attribute tag, and method information is contained within the component-extension tag, as is library information. Example 19-13 shows abbreviated code for the declarative component shown in Figure 19-2.

Example 19-13 Declarative Component Metadata in the xmlContent Tag

<af:xmlContent>
  <component xmlns="http://xmlns.oracle.com/adf/faces/rich/component">
    <display-name>myPanelBox</display-name>
    <facet>
      <description>Holds the content in the panel box</description>
      <facet-name>Content</facet-name>
    </facet>
    <attribute>
      <attribute-name>title</attribute-name>
      <attribute-class>java.lang.String</attribute-class>
      <required>true</required>
    </attribute>
    <attribute>
      <attribute-name>buttonText1</attribute-name>
      <attribute-class>java.lang.String</attribute-class>
    </attribute>
  . . .
    <component-extension>
      <component-tag-namespace>component</component-tag-namespace>
      <component-taglib-uri>/componentLib1</component-taglib-uri>
      <method-attribute>
        <attribute-name>method1</attribute-name>
        <method-signature>
          void method(javax.faces.event.ActionEvent)
        </method-signature>
      </method-attribute>
      <method-attribute>
        <attribute-name>method2</attribute-name>
        <method-signature>
          void method(javax.faces.event.ActionEvent)
        </method-signature>
      </method-attribute>
. . .
    </component-extension>
 </component>
</af:xmlContent>

Metadata for the included components is contained after the xmlContent tag. The code for these components is the same as it might be in a standard JSF page, including any attribute values you set directly on the components. Any bindings you created to the attributes or methods use the component's variables in the bindings. Example 19-14 shows the code for the panelBox component with the three buttons in the toolbar. Notice that the facetRef tag appears as a child to the panelBox component, as any content a page developer will add will then be a child to the panelBox component.

Example 19-14 Components in a Declarative Component

<af:panelBox text="#{attrs.title}" inlineStyle="width:25%;">
  <f:facet name="toolbar">
    <af:group>
      <af:toolbar>
        <af:commandToolbarButton text="#{attrs.buttonText1}"
                                 actionListener="#{component.handleMethod1}"
                                 rendered="#{attrs.display1}"/>
        <af:commandToolbarButton text="#{attrs.buttonText2}"
                                 rendered="#{attrs.display2}"
                                 actionListener="#{component.handleMethod2}"/>
        <af:commandToolbarButton text="#{attrs.buttonText3}"
                                 rendered="#{attrs.display3}"
                                 actionListener="#{component.handleMethod3}"/>
      </af:toolbar>
    </af:group>
  </f:facet>
  <af:facetRef facetName="Content"/>
</af:panelBox>

The first time you use the wizard to create a declarative component in a project, JDeveloper automatically creates the declarativecomp-metadata.xml file, which is placed in the /ViewController/src/META-INF directory in the file system.

For each declarative component that you define using the wizard, JDeveloper creates a declarative component definition file (for example, componentDef1.jspx), and adds an entry to the declarativecomp-metadata.xml file. Example 19-15 shows an example of the declarativecomp-metadata.xml file.

Example 19-15 Sample declarativecomp-metadata.xml File

<declarativeCompDefs
  xmlns="http://xmlns.oracle.com/adf/faces/rich/declarativecomp">
  <declarativecomp-jsp-ui-def>
    /componentDef1.jspx
  </declarativecomp-jsp-ui-def>
  <declarativecomp-taglib>
    <taglib-name>
      dCompLib1
    </taglib-name>
    <taglib-uri>
      /dcomponentLib1
    </taglib-uri>
    <taglib-prefix>
      dc
    </taglib-prefix>
  </declarativecomp-taglib>
</declarativeCompDefs>

Note:

When you rename or delete a declarative component in the Application Navigator, JDeveloper renames or deletes the declarative component definition file in the file system, but you must manually change or delete the declarative component entry in the declarativecomp-metadata.xml file, and update or remove any JSF pages that use the declarative component.

The declarativecomp-metadata.xml file contains the names, paths, and tag library information of all the declarative components you create in the project. When you deploy the project, the metadata is used by JDeveloper to create the JSP tag libraries and Java classes for the declarative components.

19.4.3 How to Deploy Declarative Components

Declarative components require a tag library definition (TLD) in order to be displayed. JDeveloper automatically generates the TLD when you deploy the project. Because of this, you must first deploy the project that contains your declarative components before you can use them. This means before you can use declarative components in a project, or before you can share declarative components with other developers, you must deploy the declarative component definitions project to an ADF Library JAR. For instructions on how to deploy a project to an ADF Library JAR, see the "Reusing Application Components" chapter of the Oracle Fusion Middleware Fusion Developer's Guide for Oracle Application Development Framework.

Briefly, when you deploy a project that contains declarative component definitions, JDeveloper adds the following for you to the ADF Library JAR:

  • A component tag class (for example, the componentDef1Tag.class) for each declarative component definition (that is, for each componentDef component)

  • One or more JSP TLD files for the declarative components, using information from the project's declarativecomp-metadata.xml file

To use declarative components in a consuming project, you add the deployed ADF Library JAR to the project's properties. For instructions on how to add an ADF Library JAR, see the "Reusing Application Components" chapter of the Oracle Fusion Middleware Fusion Developer's Guide for Oracle Application Development Framework. By adding the deployed JAR, JDeveloper automatically inserts the JSP tag library or libraries (which contain the reusable declarative components) into the project's properties, and also displays them in the Component Palette.

19.4.4 How to Use Declarative Components in JSF Pages

In JDeveloper, you add declarative components to a JSF page just like any other UI components, by selecting and dragging the components from the Component Palette, and dropping them into the desired locations on the page. Your declarative components appear in a page of the palette just for your tag library. Figure 19-6 shows the page in the Component Palette for a library with a declarative component.

Figure 19-6 Component Palette with a Declarative Component

Declarative component in the Component Palette

When you drag a declarative component that contains required attributes onto a page, a dialog opens where you enter values for any defined attributes.

Once the declarative component is added to the page, you must manually bind the declarative methods to actual methods on managed beans.

Before proceeding with the following procedure, you must already have added the ADF Library JAR that contains the declarative components to the project where you are creating JSF pages that are to consume the declarative components. For instructions on how to add an ADF Library JAR, see the "Reusing Application Components" chapter of the Oracle Fusion Middleware Fusion Developer's Guide for Oracle Application Development Framework.

To use declarative components in a JSF page:

  1. In the Application Navigator, double-click the JSF page (or JSF page template) to open it in the visual editor.

  2. In the Component Palette, select the declarative components tag library name from the dropdown list. Drag and drop the desired declarative component onto the page. You can add the same declarative component more than once on the same page.

    If the declarative component definition contains any required attributes, JDeveloper opens a dialog for you to enter the required values for the declarative component that you are inserting.

    Note:

    If you want to use ADF Model layer bindings as values for the attributes, then to create these bindings manually by using the Expression Builder to locate the needed binding property.
  3. Add components by dragging and dropping components from the Component Palette in the facets of the template. In the Structure window, expand the structure until you see the element for the declarative component, for example, dc:myPanelBox, where dc is the tag library prefix and myPanelBox is the declarative component name.

    Under that are the facets (for example, f:facet - content) that have been defined in the declarative component definition. You add components to these facets.

    You cannot add content directly into the declarative component; you can drop content into the named facets only. The types of components you can drop into a facet may be dependent on the location of the facetRef tag in the declarative component definition. For example, if you have defined facetRef to be a child of table in the declarative component definition, then only column components can be dropped into the facet because table accepts column children only.

    Note:

    You cannot place any components as direct children of a declarative component. All content to appear within a declarative component must be placed within a facet of that component.
  4. In the Structure window, again select the declarative component element, for example, dc:myPanelBox. The Property Inspector displays all the attributes and methods that have been predefined in the declarative component definition (for example, title). The attributes might have default values.

    You can assign static values to the attributes, or you can use EL expressions (for example, #{myBean.somevalue}). For any of the methods, you must bind to a method that uses the same signature as the declared method defined on the declarative component.

    At runtime, the attribute value will be displayed in the appropriate location as specified in the declarative component definition by the EL expression that bears the name of the attribute (for example, #{attrs.someAttributeName}).

  5. If you need to include resources such as CSS or JavaScript, then you need to include these using the af:resource tag. For more information, see Section 19.5, "Adding Resources to Pages."

19.4.5 What Happens When You Use a Declarative Component on a JSF Page

After adding a declarative component to the page, the visual editor displays the component's defined facets as named boxes, along with any content that is rendered by components defined in the component layout section of the declarative component definition.

Like other UI components, JDeveloper adds the declarative component tag library namespace and prefix to the jsp:root tag in the page when you first add a declarative component to a page, for example:

<jsp:root xmlns:dc="/dcomponentLib1: ..>

In this example, dc is the tag library prefix, and /dcomponentLib1 is the namespace.

JDeveloper adds the tag for the declarative component onto the page. The tag includes values for the component's attributes as set in the dialog when adding the component. Example 19-16 shows the code for the MyPanelBox declarative component to which a user has added a panelGroupLayout component that contains three outputFormatted components.

Example 19-16 JSF Code for a Declarative Component that Contains Content

<dc:myPanelBox title="My Panel Box" buttonText1="Button 1"
               display1="true" display2="true" buttonText2="Button 2"
               display3="false">
  <f:facet name="Content">
    <af:panelGroupLayout layout="scroll">
      <af:outputFormatted value="outputFormatted1"
                          styleUsage="instruction"/>
      <af:outputFormatted value="outputFormatted2"
                          styleUsage="instruction"/>
      <af:outputFormatted value="outputFormatted3"
                          styleUsage="instruction"/>
    </af:panelGroupLayout>
  </f:facet>
</dc:myPanelBox>

19.4.6 What Happens at Runtime

When a JSF page that consumes a declarative component is executed:

  • The declarative component tag in the consuming page locates the declarative component tag class and definition file that contains the declarative component metadata and layout.

  • The component subtree defined in the layout section of the componentDef tag is instantiated and inserted into the consuming page's component tree at the location identified by the declarative component tag in the page.

  • The componentDef tag sets the value of the var attribute so that the declarative component can internally reference its own attributes. The declarative component just sets the attribute values; the runtime maps those values into the attributes defined in the componentDef tag.

  • Using declarative component metadata, the declarative component applies any default values to its attributes and checks for required values.

  • The consuming page passes facet contents into the declarative component by using the facet tag. The facet contents of each facet tag are inserted into the appropriate location on the declarative component as specified by the corresponding facetRef tag in the layout section of the componentDef tag.

19.5 Adding Resources to Pages

You should use the af:resource tag to add CSS or JavaScript to pages, page templates, or declarative components. This tag is especially useful for page templates and declarative components because resources can only be added to the page (in the HTML head element). When you can use this tag in page templates and declarative components, the resources will be added to the consuming page during JSP execution. If this tag is not used, browsers may need to re-layout pages that use page templates and declarative components whenever it encounters a style or link tag. The resources can be added to the page during any page request, but they must be added before the document component is rendered.

The resource tag can be used with PPR. During PPR, the following requirements apply:

  • URL resources are compared on the client before being added to the page. This ensures duplicates are not added.

  • CSS resources are removed from the page during a PPR navigation. The new page will have the new CSS resources.

19.5.1 How to Add Resources to Page Templates and Declarative Components

You use the af:resource tag to define the location of the resource. The resource will then be added to the document header of the consuming page.

To add resources:

  1. From the Operations section of the Component Palette, drag and drop a Resource tag anywhere onto the consuming page.

  2. In the Insert Resource dialog, select either css or javascript.

  3. In the Property Inspector, enter the URI of the resource as the value for the source attribute. Start the URI with a single forward slash (/) if the URI should be context relative. Start the URI with two forward slashes if the URI should be server relative. If you start the URI with something other than one or two slashes, the URI will be resolved relative to URI location in the browser

19.5.2 What Happens at Runtime: Adding Resources to the Document Header

During JSP tag execution, the af:resource tag only executes if its parent component has been created. When it executes, it adds objects to a set in the RichDocument component. RichDocument then adds the specified resources (CSS or JavaScript) to the consuming page.