26 Creating a Basic Databound Page

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

This chapter includes the following sections:

26.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 13, "Using ADF Model in a Fusion 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).

Once you drop 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, such as committing, deleting, or creating a record. 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.

26.1.1 ADF Databound Forms Use Cases and Examples

You use forms when you need to collect or display a row of data or related data. For example, the StoreFront module contains a page that allows users to register information about themselves, as shown in Figure 26-1. This form was created by dragging and dropping the CustomerRegistration collection from the Data Controls panel.

Figure 26-1 Register Customer Form in the StoreFront Module

Registration form in the StoreFront module

When you create a form, you can also choose to add navigation, so that the user can navigate quickly between records, as shown in Figure 26-2.

Figure 26-2 Navigate Between Records in a Form

Navigate Between Records in a Form

You can also add command buttons that invoke processing on the row displayed in the form. For example, you can change values for a record and save those changes in an edit form, as shown in Figure 26-1, or you can create an input form that allows users to create a new record. Figure 26-3 shows an input form where a user can create a new address.

Figure 26-3 Input Form

input form

When the attributes to display in a form are only available at runtime, you can create a dynamic form.

26.1.2 Additional Functionality for Databound Forms

You may find it helpful to understand other ADF Faces features before you implement your forms. Additionally, once you have added a form to you page, you may find that you need to add functionality such as security. Following are links to other functionality that you may find useful.

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

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

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 Section 13.4, "Using the Data Controls Panel."

    For example, Figure 26-4 shows the FirstName attribute under the CustomerRegistration collection of the StoreServiceAMDataControl data control in the StoreFront module. This is the attribute to drop to display or enter the customer's first name.

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

    Attributes for CustomerRegistration
  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.

    • List of Values: Creates ADF LOV lists. For more information about how these lists work, see Section 5.12, "Working with List of Values (LOV) in View Object Attributes." For more information about using the lists on a JSF page, see Section 30.3, "Creating a Selection List."

    • Single selections: Creates single selection lists. For more information about creating lists on a JSF page, see Section 30.3, "Creating a Selection List."

    Note:

    These selections are your choices by default. However, the list of components available to use for an attribute can be configured as a control hint on the associated entity or view object. For more information, see Section 4.6, "Defining Attribute Control Hints for Entity Objects" and Section 5.13, "Defining UI Hints for View Objects."

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

26.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 13.4.2, "What Happens When You Use the Data Controls Panel." 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.

26.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. In the case of ADF Business Components, the actual iterator is the default row set iterator for the default row set of the view object instance in the application module's data model.

For example, if you drop the FirstName attribute under the CustomerRegistration collection, JDeveloper creates an iterator binding for the
CustomerRegistration
collection.

Tip:

There is one iterator binding created for each collection. This means that when you drop two attributes from the same collection (or drop the collection 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, it the attribute set to 25. For more information about using this attribute, see Section 26.4.2.2, "Iterator RangeSize Attribute." Example 26-1 shows the iterator binding created when you drop an attribute from the CustomerRegistration collection.

Example 26-1 Page Definition Code for an Iterator Binding for an Attribute Dropped from a Collection

<executables>
  <iterator Binds="CustomerRegistration" RangeSize="25"
            DataControl="StoreServiceAMDataControl"
            id="CustomerRegistrationIterator"/>
</executables>

For information regarding the iterator binding element attributes, see Appendix B, "Oracle ADF Binding Properties."

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 CustomerRegistration collection. This means that the iterator will manage all the CustomerRegistration objects in the collection, including determining the current CustomerRegistration or range of CustomerRegistration objects.

26.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 PrincipalName attribute under the CustomerRegistration collection as an ADF Output Text w/Label widget onto a page, JDeveloper creates an attribute binding for the PrincipalName attribute. This allows the binding to access the attribute value of the current record. Example 26-2 shows the attribute binding for PrincipalName created when you drop the attribute from the CustomerRegistration collection. Note that the attribute value references the iterator named CustomerRegistrationIterator.

Example 26-2 Page Definition Code for an Attribute Binding

<bindings>
    ...
  <attributeValues IterBinding="CustomerRegistrationIterator"
                   id="PrincipalName">
    <AttrNames>
      <Item Value="PrincipalName"/>
    </AttrNames>
  </attributeValues>
</bindings>

For information regarding the attribute binding element properties, see Appendix B, "Oracle ADF Binding Properties."

26.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 PrincipalName 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 PrincipalName's binding. This expression evaluates to the label hint set on the view object (for more information about hints, see Section 5.13, "Defining UI Hints for View Objects"). It creates another expression that binds the outputText component's value attribute to the inputValue property of the PrincipalName binding, which evaluates to the value of the PrincipalName 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 26-3 shows the code generated on the JSF page when you drop the PrincipalName attribute as an Output Text w/Label widget.

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

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

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

  • label: Bound to the label property of the control hint set on the object.

  • required: Bound to the mandatory property of the control hint.

  • columns: Bound to the displayWidth property of the control hint, which determines how wide the text box will be.

  • maximumLength: Bound to the precision property of the control hint. This control hint property determines the maximum number of characters per line that can be entered into the field.

In addition, JDeveloper adds a validator component.

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

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

You can change any of these values to suit your needs. For example, the mandatory control hint on the view object 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 control hint on the view object, and all instances will then be required. For more information about these properties, see Appendix B, "Oracle ADF Binding Properties."

26.3 Creating a Basic Form

Instead of dropping each of the individual attributes of a collection to create a form, you can a complete form that displays or collects data for all the attributes on an object.

For example, you could create a page that displays basic information about registered users in the StoreFront module by dragging and dropping the CustomerInfoVO1 collection.

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 26.5, "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 26.6, "Creating an Input Form". You can also create search forms. For more information, see Chapter 31, "Creating ADF Databound Search Forms."

26.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 collection or a structured attribute from the Data Controls panel.

Before you begin:

It may be helpful to have an understanding of basic databound forms. For more information, see Section 26.3, "Creating a Basic Form."

You may also find it helpful to understand other ADF functionality and features. For more information, see Section 26.1.2, "Additional Functionality for Databound Forms."

To create a basic form:

  1. From the Data Controls panel, select the collection that represents the data you wish to display. Figure 26-5 shows the CustomerInfoVO1 collection for the StoreServiceAMDataControl data control.

    Figure 26-5 CustomerInfo View Object in the Data Controls Panel

    CustomerInfo collection
  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 control type control 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 only 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, and are placed inside a panelFormLayout component.

    • ADF Search Form: Creates a form that can be used to execute a Query-by-Example (QBE) search. For more information, see Chapter 31, "Creating ADF Databound Search Forms."

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

    You can elect to include navigational controls that allow users to navigate through all the data objects in the collection. For more information, see Section 26.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 an operation that will perform the update. For more information, see Section 26.5, "Creating a Form to Edit an Existing Record."

26.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 business object. Example 26-5 shows some of the code generated on the JSF page when you drop the CustomerInfoVO1 collection as a default ADF Form.

Note:

If an attribute is marked as hidden on the associated view or entity object, then no corresponding UI is created for it.

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

<af:panelFormLayout id="pfl1">
  <af:inputText value="#{bindings.PersonId.inputValue}"
                label="#{bindings.PersonId.hints.label}"
                required="#{bindings.PersonId.hints.mandatory}"
                columns="#{bindings.PersonId.hints.displayWidth}"
                maximumLength="#{bindings.PersonId.hints.precision}"
                shortDesc="#{bindings.PersonId.hints.tooltip}" id="it2">
    <f:validator binding="#{bindings.PersonId.validator}"/>
  </af:inputText>
  <af:inputText value="#{bindings.FirstName.inputValue}"
                label="#{bindings.FirstName.hints.label}"
                required="#{bindings.FirstName.hints.mandatory}"
                columns="#{bindings.FirstName.hints.displayWidth}"
                maximumLength="#{bindings.FirstName.hints.precision}"
                shortDesc="#{bindings.FirstName.hints.tooltip}"
                id="it1">
    <f:validator binding="#{bindings.FirstName.validator}"/>
  </af:inputText>
  <af:inputText value="#{bindings.LastName.inputValue}"
                label="#{bindings.LastName.hints.label}"
                required="#{bindings.LastName.hints.mandatory}"
                columns="#{bindings.LastName.hints.displayWidth}"
                maximumLength="#{bindings.LastName.hints.precision}"
                shortDesc="#{bindings.LastName.hints.tooltip}" id="it7">
    <f:validator binding="#{bindings.LastName.validator}"/>
  </af:inputText>
. . .
</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.

When you choose to create an input form using an object that contains a defined list of values (LOV), then a selectOneChoice component is created instead of an inputText component. For example, the PersonsVO view object contains a defined LOVs for the Title, Gender, MaritalStatusCode, and PersonTypeCode attributes. When you drop the Persons data control object as an ADF Form, instead of as an empty input text field, a dropdown list showing all values is created. For more information about how these lists work, see Section 5.12, "Working with List of Values (LOV) in View Object Attributes." For more information about using the lists on a JSF page, see Section 30.3, "Creating a Selection List."

Note:

If the object contains a structured attribute (an attribute that is neither a Java primitive type nor a collection), that attribute will not appear in the dialog, and it will not have a corresponding component in the form. You will need to create those fields manually.

26.4 Incorporating Range Navigation into Forms

When you create an ADF Form, if you choose 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 26-6 shows a form that would be created if you drag the CustomerInfoVO1 collection and drop it as an ADF Form that uses navigation.

Figure 26-6 Navigation in a Form

Navigation buttons in the detail page for search results

26.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 an understanding of navigation controls. For more information, see Section 26.4, "Incorporating Range Navigation into Forms."

You may also find it helpful to understand other ADF functionality and features. For more information, see Section 26.1.2, "Additional Functionality for Databound Forms."

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 persons, you would drag the Next operation associated with the Persons collection. Figure 26-7 shows the operations associated with the CustomerInfoVO1 collection.

    Figure 26-7 Operations Associated with a Collection

    Navigation operations in the DCP
  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.

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

26.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 last object in the collection, and to the first 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 buttons is clicked. Action bindings to other than iterator-level actions, for example for a custom method on an application module, or for the commit or rollback operations, will not contain this reference.

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 26-6 shows the action bindings for the navigation operations.

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

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

26.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 26-7 shows the default range size for the CustomerInfoVO iterator.

Example 26-7 RangeSize Attribute for an Iterator

<iterator Binds="CustomerInfoVO" RangeSize="25"
          DataControl="StoreServiceAMDataControl"
          id="CustomerInfoVO1Iterator"
          ChangeEventPolicy="ppr"/>

Note:

This rangeSize attribute is not the same as the rows attribute on a table component. For more information, see Table 27-1, "ADF Faces Table Attributes and Populated Values".

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 navigateable 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 26-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. For more information about action events, see Section 26.4.3, "What Happens at Runtime: How Action Events and Action Listeners Work."

Table 26-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.


26.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 be rarely 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 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 Appendix B, "Oracle ADF Binding Properties."

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

26.4.3 What Happens at Runtime: How Action Events and Action Listeners Work

An action event occurs when a command component is activated. For example, when a user clicks a Submit button, the form is submitted and, subsequently, an action event is fired. Action events might affect only the user interface (for example, a link to change the locale, causing different field prompts to display), or they might involve some logic processing in the back end (for example, a button to navigate to the next record).

An action listener is a class that wants to be notified when a command component fires an action event. An action listener contains an action listener method that processes the action event object passed to it by the command component.

In the case of the navigation operations, when a user clicks, for example, the Next button, an action event is fired. This event object stores currency information about the current data object, taken from the iterator. Because the component's actionListener attribute is bound to the execute method of the Next action binding, the Next operation is invoked when the event fires. This method takes the currency information passed in the event object to determine what the next data object should be.

In addition, when a user clicks a navigation button, only those components associated with the same iterator as the button's action binding are processed through the lifecycle. For more information, see Section 25.2.1, "What You May Need to Know About Partial Page Rendering and Iterator Bindings."

26.4.4 What You May Need to Know About the Browser Back Button and Navigating Through Records

You must use the navigation buttons to navigate through the records displayed in a form; you cannot use the browser's back or forward buttons. Because navigation forms automatically use PPR, only part of the page goes through the lifecycle, meaning that when you click a navigation button, the components displaying the data are refreshed and display new data, and you actually remain on the same page. Therefore, when you click the browser's back button, you will be returned to the page that was rendered before the page with the form, instead of to the previous record displayed in the form.

For example, say you are on a page that contains a link to view all current orders. When you click the link, you navigate to a page with a form and the first order, Order #101, is displayed. You then click Next and Order #102 is displayed. You click Next again, and Order #103 is displayed. If you click the browser's back button, you will not be shown Order #102. Instead, you will be returned to the page that contained the link to view all current orders.

26.5 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 operations that can modify data records associated with the collection or the data control itself to create command buttons. For example, you can use the Delete operation to create a button that allows a user to delete a record from the current range. Or you can use the built-in Submit button to submit changes.

Tip:

While you can use the Create operation on a form to create a new object, using the ADF Creation Form instead provides additional built-in functionality. See Section 26.6, "Creating an Input Form" for more information.

It is important to note that these operations are executed only against objects in the ADF cache. You need to use the Commit operation on the root data control to actually commit any changes to the data source. You use the data control's Rollback operation to roll back any changes made to the cached object. If the page is part of a transaction within a bounded task flow, you would most likely use these operations to resolve the transaction in a task flow return activity. For more information, see Section 22.3, "Managing Transactions in Task Flows."

26.5.1 How to Create Edit Forms

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

Before you begin:

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

You may also find it helpful to understand other ADF functionality and features. For more information, see Section 26.1.2, "Additional Functionality for Databound Forms."

To create an edit form:

  1. From the Data Controls panel, drag the collection for which you wish to create the form, and select 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. In the Edit Form Fields dialog, select Include Submit Button and click OK.

  3. You can either create new buttons for the operations you want to include, or you can rebind the Submit button so that it invokes another operation. To keep the Submit button as is and create new buttons for the operations, continue with this step. To rebind the Submit button, see Step 5.

    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. If you simply want to be able to edit the data, then the Submit button is all that is required.

    For example, if you want to be able to delete a customer record, you would drag the Delete operation associated with the CustomerInfoVO1 collection. Figure 26-8 shows the operations associated with a collection.

    Figure 26-8 Operations Associated with a Collection

    Navigation operations in the DCP
  4. From the ensuing context menu, choose either ADF Button or ADF Link.

  5. To rebind the Submit button, right-click the button in the Structure window, and choose Bind to ADF Control. In the Bind to ADF Control dialog, select the operation to which you want the button bound. Ensure that the operation you select is associated with the collection on which the form is based.

    For example, if you want to be able to delete a customer record, you would select the Delete operation associated with the CustomerInfoVO1 collection. Figure 26-8 shows the operations associated with a collection.

  6. If the page is not part of a transaction within a bounded task flow, then you need to create buttons that allow the user either to commit or roll back the changes. From the Data Controls panel, drag the Commit and Rollback operations associated with the root-level data control, and drop them as either a command button or a command link. Figure 26-9 shows the commit and rollback operations for the StoreServiceAMDataControl data control (note that for viewing simplicity, the figure omits details in the tree that appear for each view object).

    Figure 26-9 Commit and Rollback Operations for a Data Control

    The Commit operation is nested under the Operators folder.

    If the page is part of a transaction within a bounded task flow, then you can simply enter Commit and Rollback as the values for the transaction resolution when creating the task flow return activity. For more information, see Section 22.3, "Managing Transactions in Task Flows."

26.5.2 What Happens When You Use Built-in Operations to Change Data

Dropping any data control operation as a command button causes the same events as does dropping navigation operations. For more information, see Section 26.4.2, "What Happens When You Create Command Buttons."

The only difference is that the action bindings for the Commit and Rollback operations do not require a reference to the iterator, because they execute a method on the application module (the data control itself), as opposed to the iterator. Note that the Rollback action has the RequiresUpdateModel property set to false. This is because the model should not be updated before the operation is executed, since all changes need to be discarded. Example 26-9 shows the action bindings generated in the page definition file for these operations.

Example 26-9 Action Bindings for Commit and Rollback Operations

<action id="Commit" RequiresUpdateModel="true" Action="commitTransaction"
        DataControl="StoreServiceAMDataControl"/>
<action id="Rollback" RequiresUpdateModel="false"
        Action="rollbackTransaction"
        DataControl="StoreServiceAMDataControl"/>

Table 26-2 shows the built-in non-navigation operations provided on data controls and data control objects, along with the result of invoking the operation or executing an event bound to the operation. For more information about action events, see Section 26.4.3, "What Happens at Runtime: How Action Events and Action Listeners Work."

Table 26-2 More Built-in Operations

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

CreateInsert

Creates a row directly before the current row, inserts the new record into the row set, then moves the current row pointer to the new row. Note that the range does not move, meaning that the last row in the range may now be excluded from the range. For more information about using the CreateInsert operation to create objects, see Section 26.6, "Creating an Input Form."

Create

Creates a row directly before the current row, then moves the current row pointer to the new row. Note that the range does not move, meaning that the last row in the range may now be excluded from the range. Also note that the record will not be inserted into the row set, preventing a blank row should the user navigate away without actually creating data. The new row will be created when the user submits the data. For more information, see Section 27.4.5, "What You May Need to Know About Create and CreateInsert."

CreateWith
Parameters

Same as the CreateInsert operation (the new record is inserted into the row set), however uses named parameters to create the object.

Delete

Deletes the current row from the cache and moves the current row pointer to the next row in the result set. Note that the range does not move, meaning that a row may be added to the end of the range. If the last row is deleted, the current row pointer moves to the preceding row. If there are no more rows in the collection, the enabled attribute is set to disabled.

RemoveRowWithKey

Uses the row key as a String converted from the value specified by the input field to remove the data object in the bound data collection.

SetCurrentRowWith
Key

Sets the row key as a String converted from the value specified by the input field. The row key is used to set the currency of the data object in the bound data collection. For an example of when this is used, see Section 27.2.3, "What You May Need to Know About Setting the Current Row in a Table."

SetCurrentRowWith
KeyValue

Sets the current object on the iterator, given a key's value. For more information, see Section 27.2.3, "What You May Need to Know About Setting the Current Row in a Table."

ExecuteWithParams

Refreshes the data collection by first assigning new values to the named bind variables passed as parameters, then (re)executing the view object's query. You would use this operation in the same manner as you would use the CreateInsert operation to create an input form. For more information, see Section 26.6, "Creating an Input Form."

This operation appears only for view objects that have defined one or more named bind variables at design time. For more information, see Section 5.10, "Working with Bind Variables.".

Commit

Causes all items currently in the cache to be committed to the database.

Rollback

Clears the cache and returns the transaction and iterator to the initial state. Resets the ActionListener method.

Execute and Find

These operations are used only in search forms. See Chapter 31, "Creating ADF Databound Search Forms" for more information.


26.6 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 CreateInsert 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.

For example, in the StoreFront module, the customer-registration-task-flow task flow contains the createAddress method activity, which calls the CreateInsert operation on the CustomerAddress view object. Control is then passed to the addressDetails view activity, which displays a form where the user can enter a new address, as shown in Figure 26-10.

Figure 26-10 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 createInsert 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.

26.6.1 How to Create an Input Form Using a Task Flow

Instead of using command components to create new objects, you use a method activity in a task flow.

Before you begin:

Before you create the input form, you need to create a bounded task flow that will contain both the form and the method activity that will execute the CreateInsert operation. For more information, see Section 18.2, "Creating a Task Flow."

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

You may also find it helpful to understand other ADF functionality and features. For more information, see Section 26.1.2, "Additional Functionality for Databound Forms."

To create an input form:

  1. To the bounded task flow, add a method call activity. Have this activity execute the CreateInsert operation associated with the collection for which you are creating the form. For procedures on using method activities, see Section 19.5, "Using Method Call Activities."

  2. In the Property Inspector, enter a string for the fixed-outcome property. For example, the createAddress method activity in the customer-registration-task-flow task flow has editAddress as the fixed-outcome value.

  3. Add a view activity that represents the page for the input form. For information on adding view activities, see Section 18.3, "Adding Activities to a Task Flow."

  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.

    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 CreateInsert operation.

  6. Because you need to commit the new data, the application needs to execute the commit operation of the data control. To do this, you can add a button that navigates to a return activity that calls the commit operation. For procedures for using a return activity, see Section 19.7, "Using Task Flow Return Activities."

    Best Practice:

    Use the return activity unless the task flow contains data managed by more than one data control, or you need to commit the data before the end of the flow. In those cases, you can add a button to the page bound to the commit button.

    If you need to add a commit button to the page, do the following:

    1. In the Data Controls panel, drag the commit operation associated with the data control that contains the collection associated with the input form, and drop it as a command button.

    2. In the Structure window, select the command button for the commit operation.

    3. In the Property Inspector, set the action to the outcome String that will navigate back to the method activity. You then need to add a control flow case from the page back to the activity, using the same outcome value.

    4. Set the command button's disabled property to false.

      By default, JDeveloper binds the disabled attribute of the button to the enabled property of the binding, causing the button to be disabled when the enabled property is set to false. For this binding, the enabled property is false until an update has been posted. For the purposes of an input form, the button should always be enabled, since there will be no changes posted before the user needs to create the new object.

26.6.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 collection and an action binding for the CreateInsert operation in the page definition for the method activity. The CreateInsert 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 collection and attribute bindings for each of the attributes of the object in the collection, as for any other form. If you created command buttons or links using the Commit and Rollback operations, JDeveloper also creates an action bindings for those operations.

  • 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 StoreFront module contains a page that displays all the addresses for a customer in a table. The table includes an Add button that navigates to a form where you can input data for a new address. Once the address is created, you return to the page with the table and the new address is displayed. Figure 26-11 shows the customer-registration-task-flow task flow with the createAddress method activity.

Figure 26-11 Task Flow for an Input Form

Task flow for an input form

Example 26-10 shows the page definition file for the method activity.

Example 26-10 Page Definition Code for a Creation Method Activity

<executables>
  <iterator id="CustomerAddressIterator" RangeSize="25"
            Binds="CustomerAddress" DataControl="StoreServiceAMDataControl"/>
</executables>
<bindings>
  <action id="CreateInsert" IterBinding="CustomerAddressIterator"
          InstanceName="StoreServiceAMDataControl.CustomerAddress"
          DataControl="StoreServiceAMDataControl" RequiresUpdateModel="true"
          Action="createInsertRow"/>
</bindings>

26.6.3 What Happens at Runtime: CreateInsert Action from the Method Activity

When the createMethodCall activity is accessed, the CreateInsert action binding is invoked, which executes the CreateInsertRow 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.

26.6.4 What You May Need to Know About Displaying Sequence Numbers

Because the Create action is executed before the page is displayed, if you are populating the primary key using sequences, the next number in the sequence will appear in the input text field, unlike the rest of the fields, which are blank. The sequence number is displayed because the associated entity class contains a method that uses an eager fetch to generate a sequence of numbers for the primary key attribute. The eager fetch populates the value as the row is created. Therefore, using sequences works as expected with input forms.

However, if instead you've configured the attribute's type to DBSequence (which uses a database trigger to generate the sequence), the number would not be populated until the object is committed to the database. In this case, the user would see a negative number as a placeholder. To avoid this, you can use the following EL expression for the Rendered attribute of the input text field:

#{bindings.EmployeeId.inputValue.value > 0}

This expression will display the component only when the value is greater than zero, which will not be the case before it is committed. Similarly, you can simply set the Rendered attribute to false. However, then the page will never display the input text field component for the primary key.

26.7 Using a Dynamic Form to Determine Data to Display at Runtime

ADF Faces offers a library of dynamic components that includes dynamic form and dynamic table widgets that you can drop from the Data Controls panel. Dynamic components differ from standard components in that all the binding metadata is created at runtime. This dynamic building of the bindings allows you set display information using control hints on a view object instead of configuring the information in the Edit Form Fields dialog as you drop the control onto the page. Then if you want to change how the data displays, you need only change it on the view object, and all dynamic components bound to that view object will change their display accordingly. With standard components, if you want to change any display attributes (such as the order or grouping of the attributes) you would need to change each page on which the data is displayed.

For example, in the StoreFront module, you could set the Category and Field Order attribute hints on the CustomerInfoVO view object that groups the FirstName and LastName attributes together and at the top of a form (or at the leftmost columns of a table), the ConfirmedEmail and MobilePhoneNumber together and at the bottom of a form (or the rightmost columns of a table), and the MembershipID and MembershipType together and at the middle of a form or table. You could make it so that the PersonId does not display at all. For more information about control hints on view objects, see Section 5.13, "Defining UI Hints for View Objects."

Figure 26-12 shows a dynamic form at runtime created by dragging and dropping the CustomerInfoVO view object with control hints set as described previously, as a dynamic form. Note that the input fields are grayed out because the view object is nonupdateable.

Figure 26-12 Dynamic Form Displays Based on Hints Set on the View Object

Dynamic form uses UI hints for order and grouping

26.7.1 How to Use Dynamic Forms

To use dynamic forms you first need to set control hints (especially the order and grouping hints) on any corresponding view objects. Next you import the libraries for the dynamic components. You can then drop the dynamic form or table widgets onto your page.

Before you begin:

It may be helpful to have an understanding of dynamic forms. For more information, see Section 26.7, "Using a Dynamic Form to Determine Data to Display at Runtime."

You may also find it helpful to understand other ADF functionality and features. For more information, see Section 26.1.2, "Additional Functionality for Databound Forms."

To use dynamic components:

  1. Set UI hints on the corresponding view objects. For the Category hint, enter a string that can be used to group attributes together. For example, in the CustomerInfoVO hints, the FirstName and LastName attributes both have name as the value for the Category UI hint. The Field Order hint determines the order the attributes are displayed within a category. For example, in the CustomerInfoVO hints, the FirstName attribute has a Field Order value of 1 and the LastName attribute has a Field Order value of 2.

    For procedures on creating UI hints, see Section 5.13, "Defining UI Hints for View Objects."

  2. If not already included, import the dynamic component library.

    1. In the Application Navigator, right-click the view project in which the dynamic components will be used, and from the context menu, choose Project Properties.

    2. In the tree, select JSP Tag Libraries.

    3. On the JSP Tag Libraries page, click Add.

    4. In the Choose Tag Libraries dialog, select ADF Dynamic Components, and click OK.

    5. On the JSP Tag Libraries page, click OK.

  3. From the Data Controls panel, select the collection that represents the view object.

  4. Drag the collection onto the page, and from the context menu, choose Forms > ADF Dynamic Form.

    Tip:

    If dynamic components are not listed, then the library was not imported into the project. Repeat Step 2.

  5. In the Property Inspector, enter the following: for the Category field:

    • Category: Enter the string used as the value for the Category UI hint for the first group you'd like to display in your form. For example, in Figure 26-12, the Category value would be name.

    • Editable: Enter true if you want the data to be editable (the default). Enter false if the data should be read-only.

  6. Repeat Steps 7 and 8 for each group that you want to display on the form. For example, the form in Figure 26-12 is actually made up of three different forms: one for the category name, one for the category membership, and one for the category contact.

26.7.2 What Happens When You Use Dynamic Components

When you drop a dynamic form, only a binding to the iterator is created. Example 26-11 shows the page definition for a page that contains one dynamic form component created by dropping the CustomerInfoVO collection. Note that no attribute bindings are created.

Example 26-11 Page Definition Code for a Dynamic Form

<pageDefinition xmlns="http://xmlns.oracle.com/adfm/uimodel"
                version="11.1.1.53.2" id="DynamicFormPageDef"
                Package="package.pageDefs">
  <parameters/>
  <executables>
    <iterator Binds="CustomerInfoVO1" RangeSize="25"
              DataControl="StoreServiceAMDataControl"
              id="CustomerInfoVO1Iterator"/>
  </executables>
  <bindings/>
</pageDefinition>

JDeveloper inserts a a form tag which contains a dynamic form tag for each of the forms dropped. The form tag's value is bound to the iterator binding, as shown in Example 26-12. This binding means the entire form is bound to the data returned by the iterator. You cannot set display properties for each attribute individuality, nor can you rearrange attributes directly on the JSF page.

Example 26-12 JSF Page Code for a Dynamic Form

<af:document>
  <af:messages/>
  <af:form>
    <dynamic:form value="#{bindings.CustomerInfoVO1Iterator}" 
                  category="name" id="f1"/>
    <dynamic:form value="#{bindings.CustomerInfoVO1Iterator}"
                  category="member" id="f2"/>
    <dynamic:form value="#{bindings.CustomerInfoVO1Iterator}"
                  category="contact" id="f3"/>
  </af:form>
</af:document>

Tip:

You can set certain properties that affect the functionality of the form. For example, you can make a form available for upload, set the rendered property, or set a partial trigger. To do this, select the af:form tag in the Structure window, and set the needed properties using the Property Inspector.

26.7.3 What Happens at Runtime: How Attribute Values Are Dynamically Determined

When a page with dynamic components is rendered, the bindings are created just as they are when items are dropped from the Data Controls panel at design time, except that they are created at runtime. For more information, see Section 26.3.2, "What Happens When You Create a Form."

Tip:

While there is a slight performance hit because the bindings need to be created at runtime, there is also a performance gain because the JSF pages do not need to be regenerated and recompiled when the structure of the view object changes.

26.8 Modifying the UI Components and Bindings on a Form

Once you use the Data Controls panel to create any type of form (except a dynamic 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.

Note:

You cannot change how a dynamic form displays using the following procedures. You must change display information on the view object or entity object instead.

26.8.1 How to Modify the UI Components and Bindings

You can modify certain aspects of the default components dropped from the Data Controls panel. You can use the Structure window to change the order in which components are displayed, to add new components or change existing components, or to delete components. You can use the Property Inspector to change or delete bindings, or to change the label displayed for a component.

To modify default components and bindings:

  1. Use the Structure window to do the following:

    • Change the order of the UI components by dragging them up or down the tree. A black line with an arrowhead denotes where the UI component will be placed.

    • Add a UI component. Right-click an existing UI component in the Structure window and choose to place the new component before, after, or inside the selected component. You then choose from a list of UI components.

    • Bind a UI component. Right-click an existing UI component in the Structure window and choose Bind to ADF Control. You can then select the object to which you want your component bound.

    • Rebind a UI component. Right-click an existing UI component in the Structure window and choose Rebind to another ADF Control. You can then select the new control object to which you want your component bound.

    • Delete a UI component. Right-click the component and choose Delete. If you wish to keep the component, but delete the binding, you need to use the Property Inspector. See the second bullet point in Step 2.

  2. With the UI component selected in the Structure window, you can then do the following in the Property Inspector:

    • Add a non-ADF binding for the UI component. Enter an EL expression in the Value field, or use the dropdown menu and choose Edit.

    • Delete a binding for the UI component by deleting the EL expression.

    • Change the label for the UI component. By default, the label is bound to the binding's label property of its hint. This property allows your page to use the UI control hints for labels that you have defined for your entity object attributes or view object attributes. The UI hints allow you to change the value once and have it appear the same on all pages that display the label.

      You can change the label just for the current page. To do so, select the label attribute. You can enter text or an EL expression to bind the label value to something else, for example, a key in a properties or resource file.

      For example, the inputText component used to display the name of a product might have the following for its Label attribute:

      #{bindings.ProductName.hints.label}
      

      However, you could change the expression to instead bind to a key in a properties file, for example:

      #{properties['productName']}
      

      In this example, properties is a variable defined in the JSF page used to load a properties file.

26.8.2 What Happens When You Modify Attributes and Bindings

When you modify how an attribute is displayed by moving or changing the UI component, JDeveloper changes the corresponding code on the JSF page. When you use the binding editors to add or change a binding, JDeveloper adds the code to the JSF page, and also adds the appropriate elements to the page definition file.