Skip Headers
Oracle® Fusion Middleware Java EE Developer's Guide for Oracle Application Development Framework
11g Release 2 (11.1.2.1.0)

Part Number E17272-02
Go to Documentation Home
Home
Go to Table of Contents
Contents
Go to Feedback page
Contact Us

Go to previous page
Previous
Go to next page
Next
PDF · Mobi · ePub

4 Creating a Basic Databound Page

This chapter describes how to use the Data Controls panel to create databound forms using ADF Faces components.

This chapter includes the following sections:

4.1 About Creating a Basic Databound Page

You can create UI pages that allow you to display and collect information using data controls created for your business services. For example, using the Data Controls panel, you can drag an attribute for an item, and then choose to display the value either as read-only text or as an input text field with a label. JDeveloper creates all the necessary JSF tag and binding code needed to display and update the associated data. For more information about the Data Controls panel and the declarative binding experience, see Chapter 2, "Using ADF Model Data Binding in a Java EE Web Application."

Instead of having to drop individual attributes, JDeveloper allows you to drop all attributes for an object at once as a form. The actual UI components that make up the form depend on the type of form dropped. You can create forms that display values, forms that allow users to edit values, and forms that collect values (input forms).

For example, the Summit demo application contains a page that allows users to view and edit information about an order, as shown in Figure 4-1. This form was created by dragging and dropping the SOrdList accessor collection from the Data Controls panel. (The SOrdList node is nested within the customerFindAll node.)

Figure 4-1 Edit Order Form in Summit Demo Application

Web page containing an Edit Order form

Once you create the UI components, you can then drop built-in operations as command UI components that allow you to navigate through the records in a collection or that allow users to operate on the data. For example, you can create a button that allows users to delete data objects displayed in the form. You can also modify the default components to suit your needs.

4.2 Using Attributes to Create Text Fields

JDeveloper allows you to create text fields declaratively in a WYSIWYG development environment for your JSF pages, meaning you can design most aspects of your pages without needing to look at the code. When you drag and drop items from the Data Controls panel, JDeveloper declaratively binds ADF Faces text UI components to attributes on a data control using an attribute binding.

4.2.1 How to Create a Text Field

To create a text field that can display or update an attribute, you drag and drop an attribute of a collection from the Data Controls panel.

Before you begin:

It may be helpful to have a general understanding of using data control attributes to create text fields. For more information, see Section 4.2, "Using Attributes to Create Text Fields."

You will need to complete this task:

Create a data control for your session bean, as described in Section 2.2.1, "How to Create ADF Data Controls."

To create a bound text field:

  1. From the Data Controls panel, select an attribute for a collection. For a description of the icons that represent attributes and other objects in the Data Controls panel, see Table 2-1.

    For example, Figure 4-2 shows the address attribute under the customerFindAll accessor collection of the OrdersSessionEJBLocal data control in the Summit demo application. This is the attribute to drop to display or enter the first part of an address.

    Figure 4-2 Attributes Associated with a Collection in the Data Controls Panel

    Attributes of the customerFindAll collection
  2. Drag the attribute onto the page, and from the context menu choose the type of widget to display or collect the attribute value. For an attribute, you are given the following choices:

    • Text:

      • ADF Input Text w/ Label: Creates an ADF Faces inputText component with a nested validator component. The label attribute is populated.

        Tip:

        For more information about validators and other attributes of the inputText component, see the "Using Input Components and Defining Forms" chapter of the Oracle Fusion Middleware Web User Interface Developer's Guide for Oracle Application Development Framework.
      • ADF Input Text: Creates an ADF Faces inputText component with a nested validator component. The label attribute is not populated.

      • ADF Output Text w/ Label: Creates a panelLabelAndMessage component that holds an ADF Faces outputText component. The label attribute on the panelLabelAndMessage component is populated.

      • ADF Output Text: Creates an ADF Faces outputText component. No label is created.

      • ADF Output Formatted w/Label: Same as ADF Output Text w/Label, but uses an outputFormatted component instead of an outputText component. The outputFormatted component allows you to add a limited amount of HTML formatting. For more information, see the "Displaying Output Text and Formatted Output Text" section of the Oracle Fusion Middleware Web User Interface Developer's Guide for Oracle Application Development Framework

      • ADF Output Formatted: Same as ADF Output Formatted w/Label, but without the label.

      • ADF Label: An ADF Faces outputLabel component.

    • Single Selections: Creates single selection lists. For more information about creating lists on a JSF page, see Chapter 7, "Creating Databound Selection Lists."

    For the purposes of this chapter, only the text components (and not the lists) will be discussed.

4.2.2 What Happens When You Create a Text Field

When you drag an attribute onto a JSF page and drop it as a UI component, among other things, a page definition file is created for the page (if one does not already exist). For a complete account of what happens when you drag an attribute onto a page, see Section 2.3.2, "What Happens When You Use the Data Controls Panel to Create UI Components." Bindings for the iterator and attributes are created and added to the page definition file. Additionally, the necessary JSPX page code for the UI component is added to the JSF page.

4.2.2.1 Creating and Using Iterator Bindings

Whenever you create UI components on a page by dropping an item that is part of a collection from the Data Controls panel (or you drop the whole collection as a form or table), JDeveloper creates an iterator binding if it does not already exist. An iterator binding references an iterator for the data collection, which facilitates iterating over its data objects. It also manages currency and state for the data objects in the collection. An iterator binding does not actually access the data. Instead, it simply exposes the object that can access the data and it specifies the current data object in the collection. Other bindings then refer to the iterator binding in order to return data for the current object or to perform an action on the object's data. Note that the iterator binding is not an iterator. It is a binding to an iterator.

For example, if you drop the address attribute from the customerFindAll collection, JDeveloper creates an iterator binding for the OrdersSessionEJBLocal data control and accessorIterator binding for the customerFindAll collection, which in turn has the OrdersSessionEJBLocal iterator as its master binding.

Tip:

There is one accessor iterator binding created for each collection returned from an accessor. This means that when you individually drop two attributes from the same accessor (or drop the attribute twice), they use the same binding. This is fine, unless you need the binding to behave differently for the different components. In that case, you will need to manually create separate iterator bindings.

The iterator binding's rangeSize attribute determines how many rows of data are fetched from a data control each time the iterator binding is accessed. This attribute gives you a relative set of 1-n rows positioned at some absolute starting location in the overall row set. By default, the attribute is set to 25.

Example 4-1 shows the iterator bindings created when you drop an attribute from the customerFindAll accessor collection.

Example 4-1 Page Definition Code for an Iterator Accessor Binding

<executables>
  <variableIterator id="variables"/>
  <iterator Binds="root" RangeSize="25"
            DataControl="OrdersSessionEJBLocal"
            id="OrdersSessionEJBLocalIterator"/>
  <accessorIterator MasterBinding="OrdersSessionEJBLocalIterator"
                    Binds="customerFindAll" RangeSize="25"
                    DataControl="OrdersSessionEJBLocal" 
                    BeanClass="model.Customer" id="customerFindAllIterator"/>
</executables>

This metadata allows the ADF binding container to access the attribute values. Because the iterator binding is an executable, by default it is invoked when the page is loaded, thereby allowing the iterator to access and iterate over the collection returned by the customerFindAll accessor. This means that the iterator will manage all the objects in the collection, including determining the current row in the collection or determining a range of address objects.

4.2.2.2 Creating and Using Value Bindings

When you drop an attribute from the Data Controls panel, JDeveloper creates an attribute binding that is used to bind the UI component to the attribute's value. This type of binding presents the value of an attribute for a single object in the current row in the collection. Value bindings can be used both to display and to collect attribute values.

For example, if you drop the address attribute under the customerFindAll accessor as an ADF Output Text w/Label widget onto a page, JDeveloper creates an attribute binding for the address attribute. This allows the binding to access the attribute value of the current record. Example 4-2 shows the attribute binding for address created when you drop the attribute from the customerFindAll accessor. Note that the attribute value references the iterator named customerFindAllIterator.

Example 4-2 Page Definition Code for an Attribute Binding

<bindings>
  <attributeValues IterBinding="customerFindAllIterator" id="address">
    <AttrNames>
      <Item Value="address"/> 
    </AttrNames>
  </attributeValues
</bindings>

For information regarding the attribute binding element properties, see the "Oracle ADF Binding Properties" appendix of the Oracle Fusion Middleware Fusion Developer's Guide for Oracle Application Development Framework.

4.2.2.3 Using EL Expressions to Bind UI Components

When you create a text field by dropping an attribute from the Data Controls panel, JDeveloper creates the UI component associated with the widget dropped by writing the corresponding tag to the JSF page.

For example, when you drop the address attribute as an Output Text w/Label widget, JDeveloper inserts the tags for a panelLabelAndMessage component and an outputText component. It creates an EL expression that binds the label attribute of the panelLabelAndMessage component to the label property of hints created for the address's binding. This expression evaluates to the label UI hint set in the data control for the bean. It creates another expression that binds the outputText component's value attribute to the inputValue property of the address binding, which evaluates to the value of the address attribute for the current row. An ID is also automatically generated for both components.

Tip:

JDeveloper automatically generates IDs for all ADF Faces components. You can override these values as needed.

Example 4-3 shows the code generated on the JSF page when you drop the address attribute as an Output Text w/Label widget.

Example 4-3 JSF Page Code for an Attribute Dropped as an Output Text w/Label

<af:panelLabelAndMessage label="#{bindings.address.hints.label}"
                         id="plam1">
  <af:outputText value="#{bindings.address.inputValue}" id="ot1"/>
</af:panelLabelAndMessage>

If instead you drop the address attribute as an Input Text w/Label widget, JDeveloper creates an inputText component. As Example 4-4 shows, similar to the output text component, the value is bound to the inputValue property of the address binding. Additionally, the following properties are also set:

  • label: Bound to the attribute's label UI hint.

  • required: Bound to the mandatory property, which in turn references the attribute's isNotNull property (which is represented by the Mandatory option in the Details section for the attribute in the overview editor for the bean's data control structure file).

  • columns: Bound to the attribute's displayWidth UII hint, which determines how wide the text box will be.

  • maximumLength: Bound to the attribute's Precision option. This property determines the maximum number of characters per line that can be entered into the field.

  • shortDesc: Bound to the tooltip UI hint.

In addition, JDeveloper adds a validator component.

Example 4-4 JSF Page Code for an Attribute Dropped as an Input Text w/Label

<af:inputText value="#{bindings.address.inputValue}"
              label="#{bindings.address.hints.label}"
              required="#{bindings.address.hints.mandatory}"
              columns="#{bindings.address.hints.displayWidth}"
              maximumLength="#{bindings.address.hints.precision}">
              shortDesc="#{bindings.address.hints.tooltip}" id="it1">
  <f:validator binding="#{bindings.address.validator}"/>
</af:inputText>

You can change any of these values to suit your needs. For example, the isNotNull property for the attribute in the data control is set to false by default, which means that the required attribute on the component will evaluate to false as well. You can override this value by setting the required attribute on the component to true. If you decide that all instances of the attribute should be mandatory, then you can change the Mandatory option for the attribute in the data control structure file, and all instances will be required. For more information about editing attributes in a data control, see Section 3.3, "Working with Attributes."

4.3 Creating a Basic Form

Instead of dropping each of the individual attributes of a collection to create a form, you can create a complete form that displays or collects data for all the attributes on an object. For example, in the Summit demo application, the form on the EditOrder.jspx page was created by dropping the ordFindAll accessor collection from the Data Controls panel.

You can also create forms that provide more functionality than simply displaying data from a collection. For information about creating a form that allows a user to update data, see Section 4.6, "Creating a Form to Edit an Existing Record." For information about creating forms that allow users to create a new object for the collection, see Section 4.7, "Creating an Input Form." You can also create search forms. For more information, see Chapter 8, "Creating Databound Search Forms."

4.3.1 How to Create a Form

To create a form using a data control, you bind the UI components to the attributes on the corresponding object in the data control. JDeveloper allows you to do this declaratively by dragging and dropping a returned collection from the Data Controls panel.

Before you begin:

It may be helpful to have a general understanding of creating forms from data controls. For more information, see Section 4.3, "Creating a Basic Form."

You will need to complete this task:

Create a data control for your session bean, as described in Section 2.2.1, "How to Create ADF Data Controls."

To create a basic form:

  1. From the Data Controls panel, select the collection that returns the data you wish to display. Figure 4-3 shows the ordFindAll accessor returned collection.

    Figure 4-3 productFindAll Accessor in the Data Controls Panel

    Accessor return collection node and its subnodes
  2. Drag the collection onto the page, and from the context menu choose the type of form that will be used to display or collect data for the object. For a form, you are given the following choices:

    • ADF Form: Launches the Edit Form Fields dialog that allows you to select individual attributes instead of having JDeveloper create a field for every attribute by default. It also allows you to select the label and UI component used for each attribute. By default, ADF inputText components are used for most attributes. Each inputText component has the label attribute populated.

      Attributes that are dates use the InputDate component. Additionally, if a UI hint has been created for an attribute, or if the attribute has been configured to be a list, then the component set by the hint is used instead. InputText components contain a validator tag that allows you to set up validation for the attribute, and if the attribute is a number or a date, a converter is also included.

      Tip:

      For more information about validators, converters, and other attributes of the inputText component, see the "Using Input Components and Defining Forms" chapter of the Oracle Fusion Middleware Web User Interface Developer's Guide for Oracle Application Development Framework.
    • ADF Read-Only Form: Same as the ADF Form, but read-only outputText components are used. Since the form is meant to display data, no validator tags are added (converters are included). Attributes of type Date use the outputText component when in a read-only form. All components are placed inside panelLabelAndMessage components, which have the label attribute populated. The panelLabelAndMessage components are placed inside a panelFormLayout component.

  3. In the Edit Form Fields dialog, configure your form.

    You can add, remove, and reorder form fields.

    You can also include navigational controls that allow users to navigate through all the data objects in the collection. For more information, see Section 4.4, "Incorporating Range Navigation into Forms." You can also include a Submit button used to submit the form. This button submits the HTML form and applies the data in the form to the bindings as part of the JSF/ADF page lifecycle. For additional help in using the dialog, click Help. All UI components are placed inside a panelFormLayout component.

  4. If you are building a form that allows users to update data, you now need to drag and drop a method that will perform the update. For more information, see Section 4.6, "Creating a Form to Edit an Existing Record."

4.3.2 What Happens When You Create a Form

Dropping an object as a form from the Data Controls panel has the same effect as dropping a single attribute, except that multiple attribute bindings and associated UI components are created. The attributes on the UI components (such as value) are bound to properties on that attribute's binding object (such as inputValue) or to the values of control hints set on the corresponding service. Example 4-5 shows some of the code generated on the JSF page when you drop the SOrdList accessor collection as a default ADF form to create the Edit Order form.

Note:

If an attribute is marked as hidden on the associated data control structure file, then no corresponding UI is created for it.

Example 4-5 Code on a JSF Page for an Input Form

<af:panelFormLayout id="pfl1">
    <af:inputText value="#{bindings.id.inputValue}"
                  label="#{bindings.id.hints.label}"
                  required="#{bindings.id.hints.mandatory}"
                  columns="#{bindings.id.hints.displayWidth}"
                  maximumLength="#{bindings.id.hints.precision}"
                  shortDesc="#{bindings.id.hints.tooltip}" id="it1">
        <f:validator binding="#{bindings.id.validator}"/>
    </af:inputText>
    <af:inputDate value="#{bindings.dateOrdered.inputValue}"
                  label="#{bindings.dateOrdered.hints.label}"
                  required="#{bindings.dateOrdered.hints.mandatory}"
                  columns="#{bindings.dateOrdered.hints.displayWidth}"
                  shortDesc="#{bindings.dateOrdered.hints.tooltip}" id="id1">
        <f:validator binding="#{bindings.dateOrdered.validator}"/>
        <af:convertDateTime pattern="#{bindings.dateOrdered.format}"/>
    </af:inputDate>
    <af:inputDate value="#{bindings.dateShipped.inputValue}"
                  label="#{bindings.dateShipped.hints.label}"
                  required="#{bindings.dateShipped.hints.mandatory}"
                  columns="#{bindings.dateShipped.hints.displayWidth}"
                  shortDesc="#{bindings.dateShipped.hints.tooltip}" id="id2">
        <f:validator binding="#{bindings.dateShipped.validator}"/>
        <af:convertDateTime pattern="#{bindings.dateShipped.format}"/>
    </af:inputDate>
    <af:selectBooleanCheckbox value="#{bindings.orderFilled.inputValue}"
                              label="#{bindings.orderFilled.label}"
                              shortDesc="#{bindings.orderFilled.hints.tooltip}"
                              id="sbc1"/>
    <af:selectOneChoice value="#{bindings.paymentType.inputValue}"
                        label="#{bindings.paymentType.label}"
                        required="#{bindings.paymentType.hints.mandatory}"
                        shortDesc="#{bindings.paymentType.hints.tooltip}"
                        id="soc2">
        <f:selectItems value="#{bindings.paymentType.items}" id="si2"/>
    </af:selectOneChoice>
. . .
</af:panelFormLayout>

Note:

For information regarding the validator and converter tags, see the "Validating and Converting Input" chapter of the Oracle Fusion Middleware Web User Interface Developer's Guide for Oracle Application Development Framework.

4.4 Incorporating Range Navigation into Forms

When you create an ADF Form, if you elect to include navigational controls, JDeveloper includes ADF Faces command components bound to existing navigational logic on the data control. This built-in logic allows the user to navigate through all the data objects in the collection. For example, Figure 4-4 shows a form that would be created if you dragged the ordFindAll accessor and dropped it as an ADF Form that uses navigation.

Figure 4-4 Navigation in a Form

design-time view of form that contains navigation controls

4.4.1 How to Insert Navigation Controls into a Form

By default, when you choose to include navigation when creating a form using the Data Controls panel, JDeveloper creates First, Last, Previous, and Next buttons that allow the user to navigate within the collection.

You can also add navigation buttons to an existing form manually.

Before you begin:

It may be helpful to have a general understanding of navigation controls. For more information, see Section 4.4, "Incorporating Range Navigation into Forms."

You will need to complete this task:

Create a data control for your session bean, as described in Section 2.2.1, "How to Create ADF Data Controls."

To manually add navigation buttons:

  1. From the Data Controls panel, select the operation associated with the collection of objects on which you wish the operation to execute, and drag it onto the JSF page.

    For example, if you want to navigate through a collection of orders, you would drag the Next operation associated with the OrdFindAll accessor. Figure 4-5 shows the operations associated with the OrdFindAll accessor.

    Figure 4-5 Operations Associated with a Collection

    Operations for an accessor returned collection
  2. From the ensuing context menu, choose either ADF Button or ADF Link.

Tip:

You can also drop the First, Previous, Next, and Last buttons at once. To do so, drag the corresponding collection, and from the context menu, choose Navigation > ADF Navigation Buttons.

4.4.2 What Happens When You Create Command Buttons

When you drop any operation as a command component, JDeveloper:

  • Defines an action binding in the page definition file for the associated operations

  • Configures the iterator binding to use partial page rendering for the collection

  • Inserts code in the JSF page for the command components

4.4.2.1 Action Bindings for Built-in Navigation Operations

Action bindings execute business logic. For example, they can invoke built-in methods on the action binding object. These built-in methods operate on the iterator or on the data control itself, and are represented as operations in the Data Controls panel. JDeveloper provides navigation operations that allow users to navigate forward, backwards, to the first object in the collection, and to the last object.

Like value bindings, action bindings for operations contain a reference to the iterator binding when the action binding is bound to one of the iterator-level actions, such as Next or Previous. These types of actions are performed by the iterator, which determines the current object and can therefore determine the correct object to display when a navigation button is clicked.

Action bindings use the RequiresUpdateModel property, which determines whether or not the model needs to be updated before the action is executed. In the case of navigation operations, by default this property is set to true, which means that any changes made at the view layer must be moved to the model before navigation can occur. Example 4-6 shows the action bindings for the navigation operations.

Example 4-6 Page Definition Code for an Operation Action Binding

<action IterBinding="ordFindAllIterator" id="First"
         RequiresUpdateModel="true" Action="first"/>
<action IterBinding="ordFindAllIterator" id="Previous"
        RequiresUpdateModel="true" Action="previous"/>
<action IterBinding="ordFindAllIterator" id="Next"
        RequiresUpdateModel="true" Action="next"/>
<action IterBinding="ordFindAllIterator" id="Last"
        RequiresUpdateModel="true" Action="last"/>

4.4.2.2 Iterator RangeSize Attribute

Iterator bindings have a rangeSize attribute that the binding uses to determine the number of data objects to make available for the page for each iteration. This attribute helps in situations when the number of objects in the data source is quite large. Instead of returning all objects, the iterator binding returns only a set number, which then become accessible to the other bindings. Once the iterator reaches the end of the range, it accesses the next set. Example 4-7 shows the default range size for the ordFindAll iterator.

Example 4-7 RangeSize Attribute for an Iterator

<accessorIterator MasterBinding="OrdersSessionEJBLocalIterator"
                  Binds="ordFindAll" RangeSize="25"
                  DataControl="OrdersSessionEJBLocal" BeanClass="model.Ord"
                  id="ordFindAllIterator" ChangeEventPolicy="ppr"/>

Note:

This rangeSize attribute is not the same as the rows attribute on a table component.

By default, the rangeSize attribute is set to 25. This means that a user can view 25 objects, navigating back and forth between them, without needing to access the data source. The iterator keeps track of the current object. Once a user clicks a button that requires a new range (for example, clicking the Next button on object number 25), the binding object executes its associated method against the iterator, and the iterator retrieves another set of 25 records. The bindings then work with that set. You can change this setting as needed. You can set it to -1 to have the full record set returned.

Note:

When you create a navigable form using the Data Controls panel, the CacheResults property on the associated iterator is set to true. This ensures that the iterator's state, including currency information, is cached between requests, allowing it to determine the current object. If this property is set to false, navigation will not work.

Table 4-1 shows the built-in navigation operations provided on data controls and the result of invoking the operation or executing an event bound to the operation.

Table 4-1 Built-in Navigation Operations

Operation When invoked, the associated iterator binding will...

First

Move its current pointer to the beginning of the result set.

Last

Move its current pointer to the end of the result set.

Previous

Move its current pointer to the preceding object in the result set. If this object is outside the current range, the range is scrolled backward a number of objects equal to the range size.

Next

Move its current pointer to the next object in the result set. If this object is outside the current range, the range is scrolled forward a number of objects equal to the range size.

Previous Set

Move the range backward a number of objects equal to the range size attribute.

Next Set

Move the range forward a number of objects equal to the range size attribute.


4.4.2.3 EL Expressions Used to Bind to Navigation Operations

When you create command components using navigation operations, the command components are placed in a panelGroupLayout component. JDeveloper creates an EL expression that binds a navigational command button's actionListener attribute to the execute property of the action binding for the given operation.

At runtime an action binding will be an instance of the FacesCtrlActionBinding class, which extends the core JUCtrlActionBinding implementation class. The FacesCtrlActionBinding class adds the following methods:

  • public void execute(ActionEvent event): This is the method that is referenced in the actionListener property, for example #{bindings.First.execute}.

    This expression causes the binding's operation to be invoked on the iterator when a user clicks the button. For example, the First command button's actionListener attribute is bound to the execute method on the First action binding.

  • public String outcome(): This can be referenced in an Action property, for example #{bindings.Next.outcome}.

    This can be used for the result of a method action binding (once converted to a String) as a JSF navigation outcome to determine the next page to navigate to.

    Note:

    Using the outcome method on the action binding implies tying the view-controller layer too tightly to the model, so it should rarely be used.

Every action binding for an operation has an enabled boolean property that Oracle ADF sets to false when the operation should not be invoked. By default, JDeveloper binds the UI component's disabled attribute to this value to determine whether or not the component should be enabled. For example, the UI component for the First button has the following as the value for its disabled attribute:

#{!bindings.First.enabled}

This expression evaluates to true whenever the binding is not enabled, that is, when the operation should not be invoked, thereby disabling the button. In this example, because the framework will set the enabled property on the binding to false whenever the first record is being shown, the First button will automatically be disabled because its disabled attribute is set to be true whenever enabled is False. For more information about the enabled property, see the "Oracle ADF Binding Properties" appendix of the Oracle Fusion Middleware Fusion Developer's Guide for Oracle Application Development Framework.

Example 4-8 shows the code generated on the JSF page for navigation operation buttons. For more information about the partialSubmit attribute on the button, see the "Enabling Partial Page Rendering Declaratively" section of the Oracle Fusion Middleware Web User Interface Developer's Guide for Oracle Application Development Framework.

Example 4-8 JSF Code for Navigation Buttons Bound to ADF Operations

<f:facet name="footer">
   <af:panelGroupLayout>
     <af:commandButton actionListener="#{bindings.First.execute}"
                       text="First"
                       disabled="#{!bindings.First.enabled}"
                       partialSubmit="true" id="cb1"/>
     <af:commandButton actionListener="#{bindings.Previous.execute}"
                       text="Previous"
                       disabled="#{!bindings.Previous.enabled}"
                       partialSubmit="true" id="cb2"/>
     <af:commandButton actionListener="#{bindings.Next.execute}"
                       text="Next"
                       disabled="#{!bindings.Next.enabled}"
                       partialSubmit="true" id="cb3"/>
     <af:commandButton actionListener="#{bindings.Last.execute}"
                       text="Last"
                       disabled="#{!bindings.Last.enabled}"
                       partialSubmit="true" id="cb4"/>
   </af:panelGroupLayoutr>
 </f:facet>

4.5 Creating a Form Using a Method That Takes Parameters

There may be cases where a page needs information before it can display content. For these types of pages, you create the form using a returned collection from a method that takes parameters. The requesting page needs to supply the value of the parameters in order for the method to execute.

4.5.1 How to Create a Form or Table Using a Method That Takes Parameters

To create forms that require parameters, you must be able to access the values for the parameters in order to determine the record(s) to return. You access those values by adding logic to a command button on another page that will set the parameter value on some object that the method can then access.

Before you begin:

It may be helpful to have a general understanding of parameter forms. For more information, see Section 4.5, "Creating a Form Using a Method That Takes Parameters."

You will need to complete these tasks:

  • Create a data control for your session bean, as described in Section 2.2.1, "How to Create ADF Data Controls."

  • Create or identify a method on your session bean that will return the items needed to be displayed in your form. For example, the OrderSessionEJBBean.java class contains the mergeOrd(Ord) method.

Tip:

If you add a service method to your session bean after you have generated the data control, you need to refresh the Data Controls panel in order to display the new method in the panel. To refresh the panel, click the Refresh icon.

To create a form or table that uses parameters:

  1. From the Data Controls panel, drag a collection that is a return of a method that takes a parameter or parameters and drop it as any type of form.

    For example, to create a form that displays when you click a button to edit an order, you would drag and drop the Ord return, as shown in Figure 4-6.

    Figure 4-6 Return of a Custom Method That Takes Parameters

    Data Controls panel showing a method return node
  2. In the Edit Form Fields dialog, configure the form as needed and click OK.

    For help in using the dialogs, click Help.

    Because the method takes parameters, the Edit Action Binding dialog opens, asking you to set the value of the parameters.

  3. In the Action Binding Editor, enter the value for each parameter by clicking the browse (...) icon in the Value field to open the EL Expression Builder. Select the node that represents the value for the parameter.

    This editor uses the value to create the NamedData element that will represent the parameter when the method is executed. Since you are dropping a collection that is a return of the method (unlike a method bound to a command button), this method will be run when the associated iterator is executed as the page is loaded. You want the parameter value to be set before the page is rendered. This means the NamedData element needs to get this value from wherever the sending page has set it.

Tip:

If you are creating a form that displays based on input from the same page, you can use an ADF Parameter Form to create the action bindings. First drag the method from the Data Controls panel and drop it as an ADF Parameter Form. Then drag the method return and drop it as any kind of form.

4.5.2 What Happens When You Create a Form Using a Method That Takes Parameters

When you use a return of a method that takes parameters to create a form, JDeveloper:

  • Creates an action binding for the method, a method iterator binding for the result of the method, and attribute bindings for each of the attributes of the object, or in the case of a table, a table binding. It also creates NamedData elements for each parameter needed by the method.

  • Inserts code in the JSF page for the form using ADF Faces components.

Example 4-9 shows the action method binding created when you drop the Ord return of the mergeOrd(Ord) method, where the value for the parameter was set to the current row data provider of the SOrdListIterator.

Example 4-9 Method Action Binding for a Method Return

<bindings>
  <methodAction id="mergeOrd" RequiresUpdateModel="true"
                Action="invokeMethod" MethodName="mergeOrd"
                IsViewObjectMethod="false" DataControl="OrdersSessionEJBLocal"
                InstanceName="Sdata.OrdersSessionEJBLocal.dataProvider
                ReturnName="data.OrdersSessionEJBLocal.methodResults.mergeOrd_
                            OrdersSessionEJBLocal_dataProvider_mergeOrd_result">
    <NamedData NDName="productId"
               NDValue="#{bindings.SOrdListIterator.currentRow.dataProvider}"
               NDType="model.Ord"/>
  </methodAction>
...
</bindings>

4.5.3 What Happens at Runtime: Setting Parameters for a Method

Unlike a method executed when a user clicks a command button, a method used to create a form is executed as the page is loaded. When the method is executed in order to return the data for the page, the method evaluates the EL expression for the NamedData element and uses that value as its parameter. It is then able to return the correct data. If the method takes more than one parameter, each is evaluated in turn to set the parameters for the method.

For example, when the EditOrder page loads, it takes the value of the currentRow.dataProvider parameter on the SOrdListIterator and sets it as the value of the parameter needed by the mergeOrd(Ord) method. Once that method executes, it returns only the record that matches the value of the parameter. Because you dropped the return of the method to create the form, that return is the product that is displayed.

4.5.4 What You May Need to Know About Setting Parameters with Methods

There may be cases where an action on one page needs to set parameters that will be used to determine application functionality. For example, you can create a command button on one page that will navigate to another page, but a component on the resulting page will display only if the parameter value is false.

You can use a managed bean to pass this parameter between the pages, and to contain the method that is used to check the value of this parameter. A setPropertyListener component with the type property set to action, which is nested in the command button, is then used to set parameter. For more information about setting parameters using methods, see the "Setting Parameter Values Using a Command Component" section of the Oracle Fusion Middleware Fusion Developer's Guide for Oracle Application Development Framework.

Note:

If you are using task flows, you can use the task flow parameter passing mechanism. For more information, see the "Using Parameters in Task Flows" chapter of the Oracle Fusion Middleware Fusion Developer's Guide for Oracle Application Development Framework.

4.5.5 What You May Need to Know About Using Contextual Events Instead of Parameters

Often a page or a region within a page needs information from somewhere else on the page or from a different region (for more information about regions, see the "Using Task Flows as Regions" sections of the Oracle Fusion Middleware Fusion Developer's Guide for Oracle Application Development Framework). While you can pass parameters to obtain that information, doing so makes sense only when the parameters are well known and the inputs are EL-accessible to the page. Parameters are also useful when a task flow may need to be restarted if the parameter value changes.

However, suppose you have a task flow with multiple page fragments that contain various interesting values that could be used as input on one of the pages in the flow. If you were to use parameters to pass the value, the task flow would need to surface output parameters for the union of each of the interesting values on each and every fragment. Instead, for each fragment that contains the needed information, you can define a contextual event that will be raised when the page is submitted. The page or fragment that requires the information can then subscribe to the various events and receive the information through the event.

You can create and configure contextual events using a page definition file. For more information, see the "Using Contextual Events" section of the Oracle Fusion Middleware Fusion Developer's Guide for Oracle Application Development Framework.

4.6 Creating a Form to Edit an Existing Record

You can create a form that allows a user to edit the current data, and then commit those changes to the data source. To do this, you use methods that can modify data records associated with the collection to create command buttons. For example, you can use the default mergeOrd(Ord) method to create a button that allows a user to update an order.

If the page is not part of a bounded task flow, you need to use the merge or persist method associated with the collection to merge the changes back into the collection. For more information about the difference between the two, see Section 4.6.3, "What You May Need to Know About the Difference Between the Merge and Persist Methods." If the page is part of a transaction within a bounded task flow, you use the commit and rollback operations to resolve the transaction in a task flow return activity. For more information, see the "Using Task Flow Return Activities" section of the Oracle Fusion Middleware Fusion Developer's Guide for Oracle Application Development Framework.

4.6.1 How to Create Edit Forms

To use methods on a form, you follow the same procedures as with the operations.

Before you begin:

It may be helpful to have a general understanding of editable forms. For more information, see Section 4.6, "Creating a Form to Edit an Existing Record."

You will need to complete these tasks:

  • Create a data control for your session bean, as described in Section 2.2.1, "How to Create ADF Data Controls."

  • Create or identify a method on your session bean that will return the items needed to be displayed in your form. For example, the OrderSessionEJBBean.java class contains the mergeOrd(Ord) method.

To create an edit form:

  1. From the Data Controls panel, drag the collection for which you wish to create the form, and choose ADF Form from the context menu.

    This creates a form using inputText components, which will allow the user to edit the data in the fields.

  2. From the Data Controls panel, select the merge method associated with the collection of objects on which you wish the operation to execute, and drag it onto the JSF page.

    For example, if you want to be able to update an order record and will not be working with that instance again, you would drag the mergeOrd(Ord) method.

  3. From the ensuing context menu, choose either ADF Button or ADF Link.

  4. In the Edit Action Binding dialog, you need to populate the value for the method's parameter. For the merge methods (and the other default methods), this is the object being updated.

    1. In the Parameters section, use the Value dropdown list to select Show EL Expression Builder.

    2. In the Expression Builder, expand the node for the accessor's iterator, then expand the currentRow node, and select dataProvider.

      This will create an EL expression that evaluates to the data for the current row in the accessor's iterator.

    3. Click OK.

    For example, if you created a form using the ordFindAll accessor collection, then JDeveloper would have created an accessorIterator binding named ordFindAllIterator. You would need to select the dataProvider for the current row under that iterator, as shown in Figure 4-7. This reference means that the parameter value will resolve to the value of the row currently being shown in the form.

  5. In the Edit Action Binding dialog, click OK.

Figure 4-7 dataProvider for the Current Row on the ordFindAllIterator Binding

dataProvider for Current Row on OrdFindAllIterator

Note:

If the page is part of a transaction within a bounded task flow, then instead of creating a button from the merge method (or other default method), you would set that method as the value for the transaction resolution when creating the task flow return activity. For more information, see the "Using Task Flow Return Activities" section of the Oracle Fusion Middleware Fusion Developer's Guide for Oracle Application Development Framework.

4.6.2 What Happens When You Use Methods to Change Data

When you drop a method as a command button, JDeveloper:

  • Defines a method binding for the method. If the method takes any parameters, JDeveloper creates NamedData elements that hold the parameter values. For more information about NamedData elements, see Section 4.5.3, "What Happens at Runtime: Setting Parameters for a Method."

  • Inserts code in the JSF page for the ADF Faces command component. This code is similar to the code for any other command button. However, instead of being bound to the execute method of an action binding for an operation, the buttons are bound to the execute method of the action binding for the method that was dropped.

4.6.2.1 Method Bindings

Similar to when you create a button from a built-in operation, when you create a button from a method, JDeveloper creates an action binding for the method. Example 4-10 shows the action binding created when you drop the mergeOrd(Ord) method.

Example 4-10 Page Definition Code for an Action Binding Used by the Iterator

<bindings>
  <methodAction id="mergeOrd" RequiresUpdateModel="true"
                Action="invokeMethod" MethodName="mergeOrd"
                IsViewObjectMethod="false" DataControl="OrdersSessionEJBLocal"
                InstanceName="OrdersSessionEJBLocal.dataProvider"
                ReturnName="OrdersSessionEJBLocal.methodResults.mergeOrd_
                            OrdersSessionEJBLocal_dataProvider_persistOrd_result">
      <NamedData NDName="ord"
                 NDValue="#{bindings.ordFindAllIterator.currentRow.dataProvider}"
                 NDType="model.Ord/>
    </methodAction>
</bindings>

In this example, when the binding is accessed, the method is invoked because the action property value is invokeMethod.

When you drop a method that takes parameters onto a JSF page, JDeveloper also creates NamedData elements for each parameter. These elements represent the parameters of the method. For example, the mergeOrd(Ord) method action binding contains a NamedData element for the Ord parameter.

4.6.2.2 Using EL Expressions to Bind to Methods

Like creating command buttons using navigation operations, when you create a command button using a method, JDeveloper binds the button to the method using the actionListener attribute. The button is bound to the execute property of the action binding for the given method. This binding causes the binding's method to be invoked on the business service. For more information about the actionListener attribute, see the "What Happens at Runtime: How Action Events and Action Listeners Work" section of the Oracle Fusion Middleware Fusion Developer's Guide for Oracle Application Development Framework.

Tip:

Instead of binding a button to the execute method on the action binding, you can bind the button to a method in a backing bean that overrides the execute method. Doing so allows you to add logic before or after the original method runs. For more information, see Section 4.6.4, "What You May Need to Know About Overriding Declarative Methods."

Like navigation operations, the disabled property on the button uses an EL expression to determine whether or not to display the button. Example 4-11 shows the EL expression used to bind the command button to the mergeOrd(Ord) method.

Example 4-11 JSF Code to Bind a Command Button to a Method

<af:commandButton actionListener="#{bindings.merge.Ord.execute}"
                  text="mergeOrd"
                  disabled="#{!bindings.mergeOrd.enabled}"
                  id="cb1"/>

Tip:

When you drop a UI component onto a page, JDeveloper automatically gives it an ID based on the number of the same type of component previously dropped, for example, cb1, cb2. You may want to change the ID to something more descriptive, especially if you will need to refer to it in a backing bean that contains methods for multiple UI components on the page.

4.6.3 What You May Need to Know About the Difference Between the Merge and Persist Methods

If when you created your session bean, you chose to expose the merge and persist methods for a structured object, then those methods appear in the Data Controls panel and you can use them to create buttons that allow the user to merge and persist the current instance of the object. Which you use depends on whether the page will need to interact with the instance once updates are made. If you want to be able to continue to work with the instance, then you need to use the persist method.

The merge methods are implementations of the JPA EntityManager.merge method. This method takes the current instance, copies it, and passes the copy to the PersistenceContext. It then returns a reference to that persisted entity and not to the original object. This means that any subsequent changes made to that instance will not be persisted unless the merge method is called again.

The persist methods are implementations of the JPA EntityManager.persist method. Like the merge method, this method passes the current instance to the PersistenceContext. However, the context continues to manage that instance so that any subsequent updates will be made to the instance in the context.

4.6.4 What You May Need to Know About Overriding Declarative Methods

When you drop an operation or method as a command button, JDeveloper binds the button to the execute method for the operation or method. However, there may be occasions when you need to add logic before or after the existing logic. JDeveloper allows you to add logic to a declarative operation by creating a new method and property on a managed bean that provides access to the binding container. By default, this generated code executes the operation or method. You can then add logic before or after this code. JDeveloper automatically binds the command component to this new method, instead of to the execute property on the original operation or method. Now when the user clicks the button, the new method is executed. For more information, see the "Overriding Declarative Methods" section in the Oracle Fusion Middleware Fusion Developer's Guide for Oracle Application Development Framework.

4.7 Creating an Input Form

You can create a form that allows a user to enter information for a new record and then commit that record to the data source. You need to use a task flow that contains a method activity that will call the Create operation before the page with the input form is displayed. This method activity causes a blank row to be inserted into the row set which the user can then populate using a form.

Tip:

For more information about task flows, see the "Creating ADF Task Flows" part of the Oracle Fusion Middleware Fusion Developer's Guide for Oracle Application Development Framework.

For example, if you have an Address bean, you could create a new form that allows the user to create an address. You might create a create-address-task-flow task flow that contains a createAddress method activity, which calls the Create operation on the AddressFindAll accessor. Control is then passed to the createAddress view activity, which displays a form where the user can enter a new address, as shown in Figure 4-8.

Figure 4-8 Create an Address

Create address in address details page

Note:

If your application does not use task flows, then the calling page should invoke the create operation similar to the way in which a task flow's method activity would. For example, you could provide application logic within an event handler associated with a command button on the calling page.

4.7.1 How to Create an Input Form Using a Task Flow

You create an input form within a bounded task flow to ensure proper transaction handling.

Before you begin:

It may be helpful to have a general understanding of input forms. For more information, see Section 4.7, "Creating an Input Form."

You will need to complete these tasks:

  • Create a data control for your session bean, as described in Section 2.2.1, "How to Create ADF Data Controls."

  • Create a bounded task flow that will contain both the form and the method activity that will execute the Create operation. The task flow should start a new transaction. For procedures, see the "Creating a Task Flow" section of the Oracle Fusion Middleware Fusion Developer's Guide for Oracle Application Development Framework.

To create an input form:

  1. To the bounded task flow, add a method activity. Have this activity execute the Create operation associated with the accessor for which you are creating the form. For these procedures on using method activities, see the "Using Method Call Activities" section of the Oracle Fusion Middleware Fusion Developer's Guide for Oracle Application Development Framework.

    For example, to create the form that would allow users to create addresses, you would have the method activity execute the Create operation associated with the AddressFindAll accessor.

  2. In the Property Inspector, enter a string for the fixed-outcome property. For example, you might enter create as the fixed-outcome value.

  3. Add a view activity that represents the page for the input form. For information about adding view activities, see the "Using View Activities" section of the Oracle Fusion Middleware Fusion Developer's Guide for Oracle Application Development Framework.

  4. Add a control flow case from the method activity to the view activity. In the Property Inspector, enter the value of the fixed-outcome property of the method activity set in Step 2 as the value of the from-outcome of the control flow case.

  5. Open the page for the view activity in the design editor, and from the Data Controls panel, drag the collection for which the form will be used to create a new record, and choose ADF Form from the context menu.

    For example, for the form to create addresses, you would drag the AddressFindAll accessor collection from the Data Controls panel.

    Tip:

    If you want the user to be able to create multiple entries before committing to the database, do the following:
    1. In the task flow, add another control flow case from the view activity back to the method activity, and enter a value for the from-outcome method. For example, you might enter createAnother.

    2. Drag and drop a command component from the Component Palette onto the page, and set the action attribute to the from-outcome just created. This will cause the task flow to return to the method activity and reinvoke the Create operation.

  6. In the task flow, add a return activity. This return activity must execute the commit operation on the data control. For these procedures, see the "Using Task Flow Return Activities" section of the Oracle Fusion Middleware Fusion Developer's Guide for Oracle Application Development Framework.

    Tip:

    If when you set the return activity to execute the commit operation the activity shows an error, it is probably because the task flow itself is not set up to start a transaction. You need to set it to do so. For more information, see the "Managing Transactions in Task Flows" section of the Oracle Fusion Middleware Fusion Developer's Guide for Oracle Application Development Framework.
  7. Add a control flow case from the view activity to the return activity. Set the fixed-outcome attribute to a text string. For example, you might set it to return.

  8. From the Component Palette, drag and drop a button or other command component that will be used to invoke the return activity. Set the action attribute to the text string set as the fixed-outcome created in Step 4.

4.7.2 What Happens When You Create an Input Form Using a Task Flow

When you use an ADF Form to create an input form, JDeveloper:

  • Creates an iterator binding for the accessor and an action binding for the Create operation in the page definition for the method activity. The Create operation is responsible for creating a row in the row set and populating the data source with the entered data. In the page definition for the page, JDeveloper creates an iterator binding for the returned collection and attribute bindings for each of the attributes of the object in the collection, as for any other form.

  • Inserts code in the JSF page for the form using ADF Faces inputText components, and in the case of the operations, commandButton components.

For example, the form shown in Figure 4-8 might be displayed by clicking a "Create Address" link on the main page. This link then navigates to the form where you can input data for a new address. Once the address is created, and you click the Save button, you return to the main page. Figure 4-9 shows a create-address-task-flow task flow with the newAddress method activity.

Figure 4-9 Task Flow for an Input Form

Task flow for an input form

Example 4-12 shows the code in the page definition file for the method activity.

Example 4-12 Page Definition Code for a Creation Method Activity

<executables>
  <iterator Binds="root" RangeSize="25" DataControl="SupplierFacadeLocal"
            id="SupplierFacadeLocalIterator"/>
  <accessorIterator MasterBinding="SupplierFacadeLocalIterator"
                    Binds="addresses" RangeSize="25"
                    DataControl="SupplierFacadeLocal"
                    BeanClass="oracle.fodemo.supplier.model.Addresses"
                    id="addressesIterator"/>
</executables>
<bindings>
  <action IterBinding="addressesIterator" id="Create"
          RequiresUpdateModel="true" Action="createRow"/>
</bindings>

4.7.3 What Happens at Runtime: Invoking the Create Action Binding from the Method Activity

In the example above, when the newAddress method activity is accessed, the Create action binding is invoked, which executes the createRow operation, and a new blank instance for the collection is created. Note that during routing from the method activity to the view activity, the method activity's binding container skips validation for required attributes, allowing the blank instance to be displayed in the form on the page.

4.8 Modifying the UI Components and Bindings on a Form

Once you use the Data Controls panel to create any type of form, you can then delete attributes, change the order in which they are displayed, change the component used to display data, and change the attribute to which the components are bound.

For more information about modifying existing UI components and bindings, see the "Modifying the UI Components and Bindings on a Form" section of the Oracle Fusion Middleware Fusion Developer's Guide for Oracle Application Development Framework.