10 Creating and Reusing Fragments, Page Templates, and Components

This chapter describes how to create reusable content and then use that content to build portions of JSF pages or entire pages. It describes how to use page templates to define entire page layouts that can be applied to pages. It also describes how to use page fragments to build complex pages. It then describes how to create reusable declarative components using existing ADF Faces components.

This chapter includes the following sections:

10.1 About 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 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.

    The page template and the declarative component share much of the functionality. The main difference is that the page template supports ADF Model binding and ADF Controller using a page template model. Using the value attribute, you can specify which object to use as the bindings inside of the page template. If the value is a page template model binding, ADF Model page bindings may be used, and you may use the ADF page definition to determine which view to include.

    For details about creating and using page templates, see Section 10.3, "Using Page Templates," and Section 10.3.3, "How to Create JSF Pages Based on Page Templates."

  • 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 10.4, "Using Page Fragments."

  • 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.

    The declarative component is deployed as part of an ADF library JAR file. It features its own TLD file that allows you to put the component in your own namespace. The declarative component allows you to pass facets into the component and also any attributes and method expressions. Inside of the declarative component, the attributes and facets may be accessed using EL expressions It has a relatively low overhead as it does not involve ADF Model or ADF Controller, which also means that it does not have support for ADF Model transactions or ADF Controller page flows.

    Note that you should not reference individual components inside of a declarative component, and individual components within a declarative component should not reference external components. The reason is that changes in the declarative component or in the consuming page could cause the partial triggers to no longer work. For details about creating and using declarative components, see Section 10.5, "Using Declarative Components."

Tip:

If your application uses 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 Developing Fusion Web Applications with Oracle Application Development Framework.

Page templates, page fragments, and declarative components provide consistent structure and layout to the pages in an application. These building blocks can not only be reused in the same application, but also can be shared across applications. When update a building block, all the instances where it is used is automatically updated.

Page templates are data-bound templates that support both static areas that do not change and dynamic areas where they change during runtime. You can use page fragments to build modular pages. For instance, you can create page fragments for the header, footer, and company logo and reuse these fragments throughout the application. You can use declarative components when you have several components that always used in a group. By creating a declarative component, you can add it to the tag library and be able to drag and drop the declarative component from the JDeveloper Components window.

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 4.8, "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 10.6, "Adding Resources to Pages."

If you are not using an ADF task flow to navigate a portion of the page, you should not be using regions, but instead use one of the other compound components. Among the compound components, you should use a page template if you need to use bindings inside of your compound component and they differ from the bindings of the host page. You should use a declarative component if you do not need bindings for your page and do not need to use a bounded task flow as part of your page.

10.1.1 Reusable Components Use Cases and Examples

The File Explorer application uses a fileExploreorTemplate to provide a consistent look and feel to all the pages in the application. The facets of the file provide working area to place different types of information. The template defines an appCopyright facet that is used to display copyright information for every page.

The main page of the File Explorer application not only uses the page template, but also uses page fragments to contain the content for the individual facets of the template. The header.jspx page fragment contains the menu commands for the application.

If you have several components that works as a group and repeats in several places, you can define a declarative component to group these components together. Once you have created the component, you can use this declarative component like any other component. For example, you may use several inputText components to denote first name, last name, and email address. Since this three inputText components will be used repeatedly in your application, you can create a declarative component for them.

10.1.2 Additional Functionality for Reusable Components

You may find it helpful to understand other Oracle ADF features before you implement your reusable components. Following are links to other functionality that are related to reusable components.

  • For more information about customization, see the "Customizing Applications with MDS" chapter of Developing Fusion Web Applications with Oracle Application Development Framework.

  • For more information on using the Quick Start Layouts to provide a preconfigured layout, see Section 9.2.3, "Using Quick Start Layouts."

  • For information about using model parameters and ADF Model data bindings, see the "Using Page Templates" section in Developing Fusion Web Applications with Oracle Application Development Framework

  • For information about packaging a page template into an ADF Library JAR file for reuse, see the "Reusing Application Components" chapter of Developing Fusion Web Applications with Oracle Application Development Framework.

10.2 Common Functionality in Reusable Components

Page templates and declarative components share several common functionalities.

10.2.1 Page in Request Scope

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. You should use backingBeanScope for declarative components and page templates. For more information about scopes, see Section 5.6, "Object Scope Lifecycles."

10.2.2 Access to Child Components for Customization

You can control whether child components of a page template or declarative component can be changed by external reference. For example, you can enable or disable the customization of the child components. Both af:pageTemplateDef and af:componentDef has a definition attribute that controls access. When definition is set to public, then the direct child components can be customized, while definition is set to private, the child components cannot be customized. The default value is private. You can modify definition by editing the source file or by using the Properties window.

For more information about customization, see the "Customizing Applications with MDS" chapter of Developing Fusion Web Applications with Oracle Application Development Framework.

10.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 10-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 9, "Organizing Content on Web Pages."

Figure 10-1 Quick Layouts

This image is described in the surrounding text

To use page templates in an application, you first create a page template definition. Page template definitions must be either Facelets or JSP XML documents 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. The page that uses the template must contain the document 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 10-1.

Example 10-1 Facet Definition in a Template

<facet>  <description> 
    <![CDATA[Area to put a link 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 10-2, 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 10-2 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:

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 10-2 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 10-3

Example 10-3 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. Page templates also support dynamic attributes as an inline tag. For example, af:pageTemplate headerSize="70" is valid syntax.

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 10-4.

Example 10-4 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 32.3, "Manually Defining Resource Bundles and Locales."

You can nest templates when you need to reuse the same content across multiple templates. For example, say your application will have three different types of pages, but the header and footer will always be the same. Instead of having to include the same header and footer design in three different templates, you can create a header template and a footer template, and then simply nest those templates into each of the different page templates.

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 10.6, "Adding Resources to Pages."

10.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.

Before you begin:

It may be helpful to have an understanding of page templates. For more information, see Section 10.3, "Using Page Templates."

You may also find it helpful to understand functionality that can be added using other ADF Faces features. For more information, see Section 10.1.2, "Additional Functionality for Reusable Components."

To create a page template definition:

  1. In the Applications window, right-click the node where you wish to create and store page templates and choose New > ADF Page Template.

  2. In the Create a Page Template dialog, 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.
  3. Accept the directory name for the template definition, or choose a new location.

    If the page template is intended to be packaged as an ADF Library, you should not accept the default directory name. You should try to specify a unique directory name so that it will be less likely to clash with page templates from other ADF Libraries.

  4. Select either Facelets or JSP XML as the document type.

  5. Enter a Page Template name for the page template definition, and click Next.

  6. In the Optionally add starting content page of the Create a a Page Template dialog, select one of the template choices, then the template, and click Next.

    • Blank Template: Select if you want start using a blank page.

    • Copy Existing Template: Select if you want to start with an existing template.

    • Copy Quick Start Layout: Select if you want to use various predefined templates featuring one, two, or three column layout.

  7. In the Add facet definitions and attribute page of the Create a Page Template dialog, you can add facets and attributes.

    • In the Facet Definitions section, click Add to add a facet name and description.

      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.

      Tip:

      If you plan on nesting templates or using more than one template on a page, to avoid confusion, use unique names for the facets in all templates.
    • In the Attributes section, click Add to add an attribute.

      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 class type (for example, java.lang.String). Note that whatever consumes the attribute (for example an attribute on a component that you configure in Step 13) 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.

    • Click Next.

  8. If the page template contents use ADF Model data bindings, select the Create Page Definition checkbox, and click Add to add one or more model parameters. For information about using model parameters and ADF Model data bindings, see the "Using Page Templates" section in Developing Fusion Web Applications with Oracle Application Development Framework.

    Once you complete the wizard, JDeveloper displays the page template definition file in the visual editor. Example 10-5 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 Properties window.

    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 10-5 Component Metadata in Page Template Definition

    <af:pageTemplateDef var="attrs">
      <af:xmlContent>
        <component xmlns="http://xmlns.oracle.com/adf/faces/rich/component">
          <description/>
          <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>
    
  9. In the Components window, drag and drop a component to the page.

    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 should never add a document tag to a page template.

    You can add any number of components to the layout section. However, you should only have one root component in a template. 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 9, "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 10.5, "Using Declarative Components." For information about using databound components in page templates, see the "Using Page Templates" section in Developing Fusion Web Applications with Oracle Application Development Framework.

  10. To nest another template into this template, in the Components window, from the Layout panel, in the Core Structure group, drag and drop a Template onto the page.

    Note:

    You cannot nest an ADF databound template in a template that does not use ADF data binding, or in a declarative component.

    Additionally, a nested template cannot be used more than one per rendering. For example, it cannot be used as a child to a component that stamps its children, such as a table or tree.

  11. In the Insert Template dialog, select the template that you want to nest.

    Tip:

    The dialog displays all the templates that are included in the current project or that are provided in an ADF Library. For more information about ADF Libraries, see the "Reusing Application Components" chapter of Developing Fusion Web Applications with Oracle Application Development Framework.
  12. In the Components window, from the Layout panel, in the Core Structure group, drag a Facet and drop it to 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 Facet 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.

    Note:

    If you have nested another template into this template, you must create facet references for each facet in the nested template as well as this template.
  13. 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 10-5, 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}">
    
  14. 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="secDecor">
      <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 10.4.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.

10.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 in Developing Fusion Web Applications with Oracle Application Development Framework.

The first time you use the wizard to create a 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 10-6 shows an example of the pagetemplate-metadata.xml file.

Example 10-6 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 Applications window, 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.

10.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 file. For information about deploying a project, see the "Reusing Application Components" chapter of Developing Fusion Web Applications with 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.

Before you begin:

It may be helpful to have an understanding of page templates. For more information, see Section 10.3, "Using Page Templates."

You may also find it helpful to understand functionality that can be added using other ADF Faces features. For more information, see Section 10.1.2, "Additional Functionality for Reusable Components."

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

  1. Follow the instructions in Section 3.4.1, "How to Create JSF Pages" to open the Create JSF Page dialog. In the dialog, select a page template to use from the available selections.

    Tip:

    Only page templates that have been created using the template wizard in JDeveloper are available for selection when you have selected ReferenceADF Page Template.

    Tip:

    Instead of basing the whole page on a template, you can use a template for an area of a page. For example, you may have a template to be used just in the headers of your pages. To apply a template to an area of your page, from the Layout panel of the Components window, drag and drop a Template into the desired component.

    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 Properties window, 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 Components window 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 Developing Fusion Web Applications with Oracle Application Development Framework.
  4. In the Structure window, select af:pageTemplate. Then, in the Properties window, 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 10-7).

    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 Properties window 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 10.6, "Adding Resources to Pages."

10.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 10-7. 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 10-7 JSF Page that References a Page Template

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

10.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 in Developing Fusion Web Applications with Oracle Application Development Framework.

10.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 in template-based pages, you should not reference an individual component inside a page template. Changes made to the page template or its consuming page may cause the partial triggers to work improperly. For more details, see Section 6.3.8, "What You May Need to Know About Using Naming Containers."

10.4 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 5.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 node hierarchy of the application.

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

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

Example 10-8 header.jspx Page Fragment

<?xml version='1.0' encoding='UTF-8'?>
<ui:composition xmlns:jsp="http://java.sun.com/JSP/Page" version="2.1"
          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>
</ui:composition>

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 10-9, which is abbreviated code from the index.jspx page.

Example 10-9 File Explorer Index JSF Page Includes Fragments

<?xml version='1.0' encoding='utf-8'?>
<ui:composition xmlns:jsp="http://java.sun.com/JSP/Page" version="2.1" 
          xmlns:f="http://java.sun.com/jsf/core"
          xmlns:af="http://xmlns.oracle.com/adf/faces/rich"
          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>
</ui:composition>

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 Developing Fusion Web Applications with Oracle Application Development Framework.

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

Example 10-10 Page Fragment Based on a Template

<?xml version='1.0' encoding='UTF-8'?>
<ui:composition xmlns:jsp="http://java.sun.com/JSP/Page" version="2.1"
          xmlns:af="http://xmlns.oracle.com/adf/faces/rich"
          xmlns:f="http://java.sun.com/jsf/core">
  <af:pageTemplate viewId="/someTemplateDefinition.jspx">
  .
  .
  .
  </af:pageTemplate>
</ui:composition>

10.4.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 Applications window in JDeveloper.

Before you begin:

It may be helpful to have an understanding of page fragments. For more information, see Section 10.4, "Using Page Fragments."

You may also find it helpful to understand functionality that can be added using other ADF Faces features. For more information, see Section 10.1.2, "Additional Functionality for Reusable Components."

To create a page fragment:

  1. In the Applications window, right-click the node where you wish to create and store page fragments and choose New > ADF Page Fragment.

  2. In the Create ADF Page Fragment dialog, enter a name for the page fragment file.

  3. 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.

  4. You can have your fragment pre-designed for you by using either a ADF page template, a Quick Start Layout. or start with a blank page.

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

    • If you want to use a Quick Start Layout, select the Copy Quick Start Layout radio button and 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 9.2.3, "Using Quick Start Layouts."

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

  5. To define the page fragment contents, drag and drop the desired components from the Components window onto the page.

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

Example 10-11 shows an example of a page fragment that contains a menu component.

Example 10-11 Page Fragment Sample

<?xml version='1.0' encoding='UTF-8'?>
<ui:composition xmlns:jsp="http://java.sun.com/JSP/Page" version="2.1"
          xmlns:af="http://xmlns.oracle.com/adf/faces/rich">
<af:pageTemplate viewId="/MytemplateDef1.jspx" id="pt1">
  <!-- 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>
</ui:composition>

10.4.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 10-12 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 10-12 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.

10.4.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 Components window or the Applications window.

10.4.3.1 Adding a Page Fragment Using the Components Window

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

Before you begin:

It may be helpful to have an understanding of page fragments. For more information, see Section 10.4, "Using Page Fragments."

You may also find it helpful to understand functionality that can be added using other ADF Faces features. For more information, see Section 10.1.2, "Additional Functionality for Reusable Components."

To add a page fragment using the Components Window:

  1. In the Components window, in the JSP page, drag a Include and drop it on the page.

  2. 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 help with the dialog, click Help or press F1.

10.4.3.2 Adding a Page Fragment Using the Applications Window

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

Before you begin:

It may be helpful to have an understanding of page fragments. For more information, see Section 10.4, "Using Page Fragments."

You may also find it helpful to understand functionality that can be added using other ADF Faces features. For more information, see Section 10.1.2, "Additional Functionality for Reusable Components."

To add a page fragment using the Applications Window:

  1. In the Applications window, drag and drop the page fragment onto the page.

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

10.4.4 What Happens at Runtime: How Page Fragments are Resolved

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.

10.5 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:

If you want to use ADF Model layer bindings as values for the attributes, then you should use a page template instead. For more information, see Section 10.3, "Using Page Templates."

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 panelBox 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 panelBox 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 10.5.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 file 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 Components window 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 Button 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 10-2 shows how such a declarative component would look in the visual editor.

Figure 10-2 Declarative Component in the Visual Editor

This image is described in the surrounding text

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 10-3.

Figure 10-3 Displayed Declarative Component

This image is described in the surrounding text

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 10.6, "Adding Resources to Pages."

10.5.1 How to Create a Declarative Component

JDeveloper simplifies creating declarative component definitions by providing the Create ADF 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.

Before you begin:

It may be helpful to have an understanding of declarative components. For more information, see Section 10.5, "Using Declarative Components."

You may also find it helpful to understand functionality that can be added using other ADF Faces features. For more information, see Section 10.1.2, "Additional Functionality for Reusable Components."

To create a declarative component definition:

  1. In the Applications window, right-click the node where you wish to create and store declarative components and click New > From Gallery.

  2. In the New Gallery, expand Web Tier, select JSF/Facelets, then ADF Declarative Component, and click OK.

  3. In the Create ADF Declarative Components dialog, 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 Components window, 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 myPanelBox.

    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 (for example, java.lang.String). 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 browse (...) icon 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 Properties window.
  11. In the Components window, drag and drop a component 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 of Developing Fusion Web Applications with 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 Facet from the Components window Core Structure panel and drop it in the desired location on the page, JDeveloper displays the Insert Facet Definition dialog. In that dialog, select a facet name from the dropdown list, or enter a facet name, and click OK. 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 Properties window 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 Properties window to open the Expression Builder, as shown in Figure 10-4.

    Figure 10-4 Opening the Expression Builder for an Attribute in the Properties Window

    This image is described in the surrounding text

    In the Expression Builder, you can expand the Scoped Variables > attrs node to select the created attribute that should be used for the value of the attribute in the Properties window. For example, Figure 10-5 shows the Title attribute selected in the Expression Builder. Click OK to add the expression as the value for the attribute.

    Figure 10-5 Expression Builder Displays Created Attributes

    This image is described in the surrounding text
  14. To specify the methods that 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.

10.5.2 What Happens When You Create a Declarative Component

When you first use the Create ADF 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. Be aware that if componentVar is set to component then it is incompatible with JSF 2.0 and the expression will fail. You will need to set componentVar using a different variable.

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 10-13 shows abbreviated code for the declarative component shown in Figure 10-2.

Example 10-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>dcomponent1</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 10-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 10-14 Components in a Declarative Component

<af:panelBox text="#{attrs.Title}" inlineStyle="width:25%;">
  <f:facet name="toolbar">
    <af:group>
      <af:toolbar>
        <af:button text="#{attrs.buttonText1}"
                                 actionListener="#{component.handleMethod1}"
                                 rendered="#{attrs.display1}"/>
        <af:button text="#{attrs.buttonText2}"
                                 rendered="#{attrs.display2}"
                                 actionListener="#{component.handleMethod2}"/>
        <af:button 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 10-15 shows an example of the declarativecomp-metadata.xml file.

Example 10-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>
      /componentLib1
    </taglib-uri>
    <taglib-prefix>
      dc
    </taglib-prefix>
  </declarativecomp-taglib>
</declarativeCompDefs>

Note:

When you rename or delete a declarative component in the Applications window, 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.

JDeveloper also adds entries to the faces-config.xml file.

10.5.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 file. For instructions on how to deploy a project to an ADF Library JAR file, see the "Reusing Application Components" chapter of Developing Fusion Web Applications with 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 file:

  • 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 file to the project's properties. For instructions on how to add an ADF Library JAR file, see the "Reusing Application Components" chapter of Developing Fusion Web Applications with Oracle Application Development Framework. By adding the deployed JAR file, 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 Components window.

10.5.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 Components window, 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 10-6 shows the page in the Components window for a library with a declarative component.

Figure 10-6 Components Window with a Declarative Component

This image is described in the surrounding text

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 file 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 file, see the "Reusing Application Components" chapter of Developing Fusion Web Applications with Oracle Application Development Framework.

Before you begin:

It may be helpful to have an understanding of declarative components. For more information, see Section 10.5, "Using Declarative Components."

You may also find it helpful to understand functionality that can be added using other ADF Faces features. For more information, see Section 10.1.2, "Additional Functionality for Reusable Components."

To use declarative components in a JSF page:

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

  2. In the Components window, from the tag library panel, drag and drop the declarative component to 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.

  3. Add components by dragging and dropping components from the Components window 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 Properties window 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 10.6, "Adding Resources to Pages."

10.5.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 10-16 shows the code for the MyPanelBox declarative component to which a user has added a panelGroupLayout component that contains three outputFormatted components.

Example 10-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>

10.5.6 What Happens at Runtime: Declarative Components

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.

10.6 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.

  • The resource used in the af:resource tag is not the ADF skin CSS. For information on using the ADF skin, see Chapter 31, "Customizing the Appearance Using Styles and Skins."

10.6.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.

Before you begin:

It may be helpful to have an understanding of the available resources. For more information, see Section 10.6, "Adding Resources to Pages."

You may also find it helpful to understand functionality that can be added using other ADF Faces features. For more information, see Section 10.1.2, "Additional Functionality for Reusable Components."

To add resources:

  1. In the Components window, from the Layout panel, in the Core Structure group, drag and drop a Resource to the page.

  2. In the Insert Resource dialog, do the following:

    • Type: Select css or javascript from the dropdown list.

    • Resource: Enter the URI of the source of the external resource to include in the page. If the URI starts with a slash ('/'), the URI will be made context relative, if it starts with two slashes ('//'), it will be made server relative. All others are non-absolute URIs are relative to URI location in the browser. If not given, the resource content will be taken from the tag body.

  3. Click OK.

10.6.2 What Happens at Runtime: How to Add 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.