28 Creating a Basic Databound Page

This chapter describes how to create databound forms in the Fusion web application with data modeled from ADF Business Components, using ADF data controls and ADF Faces components. It describes how to create text fields from individual attributes, generate entire forms from collections for editing and creating new records, and create dynamic forms.

This chapter includes the following sections:

28.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 output text or as an input text field with a label. JDeveloper creates all the necessary JSF tags 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 17, "Using ADF Model in a Fusion Web Application."

In addition to being able to drop individual attributes, you can drop all attributes for an object at once as a form or table. This chapter includes information on creating forms that display values, forms that allow users to edit values, and forms that collect values (input forms). For information on creating tables, see Chapter 29, "Creating ADF Databound Tables."

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.

28.1.1 ADF Databound Form Use Cases and Examples

You use forms when you need to collect or display a row of data. For example, the Summit sample application for Oracle ADF contains a panel that allows users to update information about their customers as shown in Figure 28-1. This form was created by dragging and dropping the Customers collection from the Data Controls panel and then selecting the fields to display.

Figure 28-1 Customer General Information Form in the Summit ADF Sample Application

General Information form in Summit demo

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 28-2.

Figure 28-2 Navigate Between Records in a Form

form for countries with navigation buttons

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, or you can create an input form that allows users to create a new record. Figure 28-3 shows an input form where a user can create a new order.

Figure 28-3 Input Form

input form for orders in the Summit sample

Note:

When the attributes to display in a form are only available at runtime, you can create a dynamic form. For more information, see Section 28.9, "Creating a Form with Dynamic Components."

28.1.2 Additional Functionality for Databound Pages

You may find it helpful to understand other Oracle ADF features before you implement your databound pages. Following are links to other functionality that you may find useful.

28.2 Creating Text Fields Using Data Control Attributes

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.

28.2.1 How to Create a Text Field

To create an individual text field that can display or update an attribute, you drag and drop an attribute of a collection from the Data Controls panel. For ADF Business Components, the Data Controls panel is populated with elements of your data model that you have defined in one or more application modules.

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 Chapter 28, "Creating Text Fields Using Data Control Attributes."

You will need to complete these tasks:

To create a databound text field:

  1. From the Data Controls panel, select an attribute from a collection. For a description of the icons that represent attributes and other objects in the Data Controls panel, see Section 17.4, "Using the Data Controls Panel."

    For example, Figure 28-4 shows the LastName attribute under the Customers collection of the BackOfficeAppModuleDataControl data control in the Summit ADF sample application. This is the attribute to drop to display, update, or insert the customer's last name.

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

    attributes for Customers collection
  2. Drag the attribute onto the page, and from the context menu choose the type of UI component to display or collect the attribute value, as shown in Figure 28-5.

    Figure 28-5 Context Menu When Dropping Attributes on a Page

    ADF Input Text w/Label selected

    For an attribute, you are given the following choices:

    • Text:

      • ADF Input Text w/ Label: Creates an ADF Faces inputText component in which the label attribute is populated. In addition, a nested validator component is created, which you can use to add client-side validation.

        Tip:

        For more information about the various attributes of the inputText component, see the "Using Input Components and Defining Forms" chapter of Developing Web User Interfaces with Oracle ADF Faces.

      • ADF Input Text: Creates an ADF Faces inputText component without a label. In addition, a nested validator component is generated, which you can use for client-side validation.

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

      • 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 Developing Web User Interfaces with Oracle ADF Faces.

      • 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 for Business Components, see Section 5.12, "Working with List of Values (LOV) in View Object Attributes." For more information on how these lists work for adapter-based data controls, see "Creating List of Values Objects" in Developing Applications with Oracle ADF Data Controls. For more information about using the lists on a JSF page, see Section 32.3, "Creating a Selection List."

    • Single selections: Creates single selection lists. For more information about creating lists on a JSF page, see Section 32.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 information on adding control hints for adapter-based data controls, see "How to Set UI Hints on Attributes" in Developing Applications with Oracle ADF Data Controls.

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

28.2.2 What Happens When You Create a Text Field

Among other things, when you drag an attribute onto a JSF page and drop it as a UI component, 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 17.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 or JSF page code for the UI component is added to the JSF page.

28.2.2.1 Iterator Bindings Created in the Page Definition File

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 LastName attribute of the Customers collection, JDeveloper creates an iterator binding for the Customers 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. One advantage of this behavior is that the currency of components stays in sync. For example, if the page has a table and and a form dropped from the same collection, the form will show the record of the selected row in the table. If you need the binding to behave differently for the different components, you 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. When you create the iterator binding by dragging an attribute or collection on to a page, the attribute is initially set to 25. For more information about using this attribute, see Section 28.4.2.2, "Iterator RangeSize Attribute Defined." Example 28-1 shows the iterator binding created when you drop an attribute from the Customers collection.

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

<executables>
  <iterator Binds="Customers" RangeSize="25"
            DataControl="BackOfficeAppModuleDataControl"
            id="Customers"/>
</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 Customers collection. This means that the iterator will manage all the Customers objects in the collection, including determining the current Customers object or range of Customers objects.

28.2.2.2 Value Bindings Created in the Page Definition File

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

Example 28-2 Page Definition Code for an Attribute Binding

<bindings>
    ...
  <attributeValues IterBinding="CustomersIterator"
                   id=""LastName
    <AttrNames>
      <Item Value="LastName">
    </AttrNames>
  </attributeValues>
</bindings>

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

28.2.2.3 Component Tags Created in JSF Page

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 LastName 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 LastName'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 LastName binding, which evaluates to the value of the LastName 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 28-3 shows the code generated on the JSF page when you drop the LastName attribute as an Output Text w/Label widget.

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

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

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

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

  • required: Bound to the object's mandatory property.

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

  • maximumLength: Bound to the object's precision property, which 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 nests a validator tag within the inputText component. You can use this tag to create client-side validation rules to supplement any validation rules that exist in the model or business service layers.

For further information regarding the validator and converter tags, see the "Validating and Converting Input" chapter of Developing Web User Interfaces with Oracle ADF Faces.

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

<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="it1">
  <f:validator binding="#{bindings.LastName.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." For more information on changing these properties at the entity object level, see Section 4.10, "Setting Attribute Properties." For more information on changing these properties at the view object level, see Section 5.2.4, "How to Edit a View Object."

28.3 Creating Basic Forms Using Data Control Collections

Instead of dropping each of the individual attributes of a collection to create a form, you can drop the collection node to create a form from multiple attributes in the collection.

For example, you could create a page that displays basic information about customers in the Summit ADF sample application by dragging and dropping the Customers 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 28.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 28.8, "Creating an Input Form". You can also create search forms. For more information, see Chapter 33, "Creating ADF Databound Search Forms."

28.3.1 How to Create a Form Using a Data Control Collection

When you 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 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 28.3, "Creating Basic Forms Using Data Control Collections."

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

You will need to complete these tasks:

To create a basic form:

  1. From the Data Controls panel, select the collection that represents the data you wish to display. Figure 28-6 shows the Customers collection for the BackOfficeAppModuleDataControl data control.

    Figure 28-6 CustomerVO Object in the Data Controls Panel

    Customers view object and its children
  2. Drag the collection onto the page, and from the context menu choose ADF Form.

    Figure 28-7 Context Menu When Dropping a Collection to a Page

    ADF Form selected in context menu
  3. In the Create Form dialog, configure your form.

    • You can exclude attributes from appearing in the form.

    • If you do not select the Read-Only Form checkbox, ADF inputText components are used for most attributes. Each inputText component has the label attribute populated. By default, the label obtains its value from a binding to the label property on the associated binding object.

      Attributes that are dates use the InputDate component.

      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 client-side validation for the attribute. If the attribute is a number or a date, a converter is also included.

      Tip:

      For more information about the various attributes of the inputText component, see the "Using Input Components and Defining Forms" chapter of Developing Web User Interfaces with Oracle ADF Faces.

    • If you select the Read-Only Form checkbox, read-only outputText components are used. Since the form is meant to display data, no validator tags are added (though 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. This ensures that the labels are aligned appropriately with the outputText components at runtime.

    • 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 28.5, "Incorporating Range Navigation into Forms."

    • You can also include a Submit button to submit the HTML form and apply 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.

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

Note:

If you select the Fields Generated at Runtime in the Create Form dialog, the attributes to display are determined at runtime based on configuration of the business service. For more information, see Section 28.9, "Creating a Form with Dynamic Components."

28.3.2 What Happens When You Create a Form Using a Data Control Collection

Dropping an object as a form from the Data Controls panel has a similar effect as dropping a single attribute, except that multiple attribute bindings and associated UI components are created and all UI components are placed inside a panelFormLayout component. 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 28-5 shows some of the code generated on the JSF page when you drop the Customers 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 28-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:convertNumber groupingUsed="false" pattern="#{bindings.Id.format}"/>
    </af:inputText>
    <af:inputText value="#{bindings.Name.inputValue}" 
                  label="#{bindings.Name.hints.label}"
                  required="#{bindings.Name.hints.mandatory}"
                  columns="#{bindings.Name.hints.displayWidth}"
                  maximumLength="#{bindings.Name.hints.precision}"
                  shortDesc="#{bindings.Name.hints.tooltip}" id="it2">
        <f:validator binding="#{bindings.Name.validator}"/>
    </af:inputText>
    <af:inputText value="#{bindings.Phone.inputValue}" 
                  label="#{bindings.Phone.hints.label}"
                  required="#{bindings.Phone.hints.mandatory}"
                  columns="#{bindings.Phone.hints.displayWidth}"
                  maximumLength="#{bindings.Phone.hints.precision}"
                  shortDesc="#{bindings.Phone.hints.tooltip}" id="it3">
        <f:validator binding="#{bindings.Phone.validator}"/>
    </af:inputText>
. . .
</af:panelFormLayout>

For more information about the code that is generated when you drop an item from the Data Controls panel, see Section 28.2.2, "What Happens When You Create a Text Field."

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 CustomerVO view object contains defined LOVs for the CountryId and CreditRatingId attributes. When you drop the Customers data control object as an ADF Form, a dropdown list showing all values is created for each LOV (instead of an empty input text field). 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 on how these lists work for adapter-based data controls, see "Creating List of Values Objects" in Developing Applications with Oracle ADF Data Controls. For more information about using the lists on a JSF page, see Section 32.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.

28.4 Creating Command Components Using Data Control Operations

In addition to providing a representation of your data objects, the Data Controls panel also has nodes that represent standard operations for use in a form. These built-in operations enable you to declaratively handle common form functions such as navigating between records and committing changes to a database. Most operations are available for individual data collections in a data control. The Commit and Rollback operations are available on the whole data control. When you drag an operation from the Data Controls panel to a page, you are prompted to choose what kind of command component to create, such as a button or a link.

Figure 28-8 shows the operations available for the Countries collection in the Summit ADF sample application.

Figure 28-8 Data Control Collection Operations

operations for the Countries data control object

This section shows how to create command components from built-in data control operations. For information on other ways you can use command components in a databound page, see Chapter 30, "Using Command Components to Invoke Functionality in the View Layer."

28.4.1 How to Create Command Components From Operations

To create a command component based on a data control operation, you drag and drop the operation from the Data Controls panel to a page.

Before You Begin:

It may be helpful to have a general understanding of using data control operations to create command components. For more information, see Chapter 28, "Creating Command Components Using Data Control Operations."

You will need to complete these tasks:

To create a command component from an operation:

  1. From the Data Controls panel, drag the operation onto the page.

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

28.4.2 What Happens When You Create Command Components Using Operations

When you drop an operation to create a command component, JDeveloper:

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

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

  • Inserts code in the JSF page for the command component

28.4.2.1 Action Bindings Created for Operations

Action bindings execute business logic. For example, they can invoke operations on the action binding object. These operations operate on the iterator or on the data control itself.

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 to actions that are not at the iterator level, such as custom methods on an application module or 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 28-6 shows the action bindings for the navigation operations.

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

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

28.4.2.2 Iterator RangeSize Attribute Defined

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

Example 28-7 RangeSize Attribute for an Iterator

<iterator Binds="Customers" RangeSize="25"
          DataControl="BackOfficeAppModuleDataControl"
          id="CustomersIterator"
          ChangeEventPolicy="ppr"/>

Note:

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

When the iterator binding is initially generated, 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. If the RangeSize attribute is not specified, the full record set is returned.

28.4.2.3 EL Expressions Created to Bind to Operations

When you create command components using data control operations, JDeveloper creates an EL expression that binds a 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 breaks the separation between the view-controller layer and the model layer, 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 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 Appendix B, "Oracle ADF Binding Properties."

Example 28-8 shows the code generated after dropping the Create and Delete operations as buttons on a page.

Example 28-8 JSF Code For Command Buttons Bound to ADF Operations

<af:button actionListener="#{bindings.Create.execute}" text="Create"
           disabled="#{!bindings.Create.enabled}" id="b5"/>
<af:button actionListener="#{bindings.Delete.execute}" text="Delete"
           disabled="#{!bindings.Delete.enabled}" id="b6"/>

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

When the user clicks a command component, the form is submitted and then 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). That event object then takes information about the current data object from the iterator and then passes it to the action binding's method, which is bound to the command component through its actionListener attribute.

Note:

An action listener is a class that registers 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.

For example, when the user clicks a Delete button that was created from the ADF Delete operation, 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 Delete action binding, the Delete operation is invoked when the event fires. This method takes the currency information passed in the event object to determine which data object to delete.

Typically, the actionListener property's value is in the form of an EL expression. For example, if the value of the actionListener attribute is {bindings.Delete.execute}, the execute() method of the Delete action binding is called.

28.4.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 Section 30.4, "Overriding Declarative Methods."

28.5 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 28-9 shows a form that would be created if you drag the Countries collection and drop it as an ADF Form that uses navigation.

Figure 28-9 Navigation in a Form

form for countries with navigation buttons

Table 28-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 28.4.3, "What Happens at Runtime: How Action Events and Action Listeners Work."

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


28.5.1 How to Manually 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 28.5, "Incorporating Range Navigation into Forms."

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

You will need to complete these tasks:

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 forward through a collection of countries, you would drag the Next operation associated with the Countries collection. Figure 28-8 shows the operations associated with the Countries 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.

28.5.2 What Happens When You Manually Add Navigation Buttons

When you drop a navigation operation from the Data Controls panel, 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

  • Inserts the partialSubmit attribute for the component in the JSF page and sets it to true in order to fire a partial page request when the button is clicked. For more information, see the "Using Partial Triggers" section of Developing Web User Interfaces with Oracle ADF Faces.

For more information on code generated for command components, see Section 28.4.2, "What Happens When You Create Command Components Using Operations."

Example 28-9 shows the code generated on the JSF page for navigation operation buttons.

Example 28-9 JSF Code for Navigation Buttons Bound to ADF Operations

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

28.5.3 What Happens at Runtime: Navigation Controls

When the user clicks a navigation control button, an action event is fired. That event object then takes information about the current data object from the iterator and then passes it to the operation's method, which is bound to the button through its actionListener attribute.

For more information, see Section 28.4.3, "What Happens at Runtime: How Action Events and Action Listeners Work."

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 27.2.1, "What You May Need to Know About Partial Page Rendering and Iterator Bindings."

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

28.5.5 What You May Need to Know About the CacheResults Property

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.

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

For data controls based on ADF Business Components or on EJB session beans that have an explicit commit model, 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 24.3, "Managing Transactions in Task Flows."

28.6.1 How to Create an Edit Form

To create an edit form, you drop a collection on your page as a form and then drop the appropriate operations as command components.

Before you begin:

It may be helpful to have an understanding of creating edit forms. For more information, see Section 28.6, "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 28.1.2, "Additional Functionality for Databound Pages."

You will need to complete these tasks:

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. In the Create Form dialog, set the fields and buttons that you would like added to the form and click OK.

  3. Optionally, from the Data Controls panel, select any additional operation associated with the collection that you would like to add to the form, drag it to the page, and choose ADF Button or ADF Link from the context menu.

    For example, if you want to be able to delete a country, you would select the Delete operation associated with the Countries collection. Figure 28-10 shows the operations associated with the Countries collection.

    Figure 28-10 Operations Associated with a Collection

    operations for the Countries collection
  4. Add operations to the page to save or cancel changes.

    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 28-11 shows the commit and rollback operations for the BackOfficeAppModuleDataControl data control.

    Figure 28-11 Commit and Rollback Operations for a Data Control

    Commit and Rollback operations for a data control

    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 24.3, "Managing Transactions in Task Flows."

    If you are basing the form on a data control that is based on business services other than ADF Business Components, the Commit and Rollback operations might not be available. For more information, see Section 28.6.3, "What You May Need to Know About Working With Data Controls for Stateless Business Services."

  5. Optionally, change the autoSubmit property of each editable field to true.

    Doing so enables any user changes to be submitted to the page when tabbing out of the field and thus enabling the Commit and Rollback operations, if they have not already been enabled by another sequence of events, such as a change to a field plus a button click.

    You can access the autoSubmit property for a field by selecting the field and then scrolling to the Behavior section in the Properties window.

Tip:

If the same page on which you create your edit form also has a table created from the same collection as the form, the table and the form use the same iterator binding, which enables the user to select the record to edit in the form by selecting a row in the table. For more information on creating databound tables, see Section 29.2, "Creating a Basic Table."

28.6.2 What Happens When You Create Edit Forms

For information on what happens when you drop a collection on to a page, see Section 28.3.2, "What Happens When You Create a Form Using a Data Control Collection.".

Dropping any data control operation as a command button causes code generation similar to when you drop navigation operations. For more information, see Section 28.4.2, "What Happens When You Create Command Components Using Operations."

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 28-10 shows the action bindings generated in the page definition file for these operations.

Example 28-10 Action Bindings for Commit and Rollback Operations

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

Table 28-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 28.4.3, "What Happens at Runtime: How Action Events and Action Listeners Work."

Table 28-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 28.8, "Creating an Input Form."

Note: CreateInsert is only available for data controls based on ADF Business Components application modules.

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.

For data controls based on application modules and most other business services, 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 29.4.5, "What You May Need to Know About Create and CreateInsert." However, for JPA-based data controls, the Create operation does insert data into the row set and can be configured to persist the data. For more information, see "Data Control Built-in Operations" in Developing Applications with Oracle ADF Data Controls.

CreateWith
Parameters

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

Note: Create With Parameters is only available for data controls based on ADF Business Components application modules.

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 29.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 29.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 28.8, "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.".

For EJB and bean data controls, this operation is only available on data control collection objects that are based on parameterized queries.

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 33, "Creating ADF Databound Search Forms" for more information.


28.6.3 What You May Need to Know About Working With Data Controls for Stateless Business Services

When you create user interfaces based on ADF Business Components services, any data changes that a user makes are not propagated to the underlying database until the user triggers the Commit operation through a command component.

For user interfaces that are based on data controls for stateless business services, such as stateless EJB session beans or RESTful web services, the Commit and Rollback operations are not available. In such cases, you can use custom methods to handle interactions with the underlying database. In the case of EJB data controls, any persistEntity and mergeEntity methods in the session bean are exposed through the Data Controls panel, and you can create command components from them. For more information, see "About Commit Models for EJB Session Beans" in Developing Applications with Oracle ADF Data Controls.

28.7 Using Parameters to Create a Form

In Oracle ADF, there are several ways that you can create a form where the record that is displayed is determined by an input parameter. The following are some of those mechanisms:

  • Create an ADF Parameter Form based on a data control collection's ExecuteWithParams operation or on a custom method that takes parameters.

  • Pass a parameter to the form through a task flow.

  • Nest a setPropertyListener tag within a command component and provide application logic within a managed bean to access the parameters and invoke any needed logic.

This section covers the creation of ADF parameter forms based on the ExecuteWithParams operation. For information on passing parameters to a form through a task flow, see Chapter 22, "Using Parameters in Task Flows" and Section 23.3, "Specifying Parameters for an ADF Region." For information on using the setPropertyListener tag, see Section 30.3, "Setting Parameter Values Using a Command Component."

The ExecuteWithParams operation is available only for data control objects that contain parameters, such as those based on view objects containing bind variables and those based on JPA-based beans that contain named queries with parameters. For example, the Summit ADF sample application contains a view object instance called SalesPeople, which is based on the EmpVO view object, which contains the bind variable TitleIdBind. So, as shown in Figure 28-12, the SalesPeople object contains an ExecuteWithParams operation with a subnode for the TitleIdBind parameter.

Figure 28-12 ExecuteWithParams Operation in the Data Controls Panel

ExecuteWithParams node and TitleIdBind parameter

View object bind variables and JPA parameterized queries allow you to supply attribute values at runtime to the view object or view criteria. The ExecuteWithParams operation 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. For more information about bind variables in view objects, see Section 5.10, "Working with Bind Variables." For more information on named parameters in JPA queries, see "EJB Data Control Prerequisites and Considerations" in Developing Applications with Oracle ADF Data Controls.

28.7.1 How to Create a Form Using Parameters

To create a form using parameters, you drop the ExecuteWithParams operation of a collection on to a page as an ADF Parameter Form and then drop the collection itself as an ADF Form.

Before you begin:

It may be helpful to have an understanding of creating parameter forms. For more information, see Section 28.7, "Using Parameters to Create a Form."

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

You will need to complete these tasks:

To create a parameter form based on the ExecuteWithParams operation:

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

  2. In the Create Form dialog, select the parameters on which you want users to be able to query and click OK.

  3. From the Data Controls panel, drag the corresponding collection, and drop it as the type of table or form that you want to display the results of the query based on the user input.

Note:

You can also declaratively incorporate selection lists into parameter forms. To create a selection list, drag a parameter node that is a child of the ExecuteWithParams operation on to the form. Then drag the ExecuteWithParams operation and drop it as a button.

28.7.2 What Happens When You Create a Parameter Form

When you drop the ExecuteWithParams operation as a parameter form, JDeveloper:

  • Inserts code in the JSF page for the form using inputText components bound to the attribute bindings, and a button component bound to the ExecuteWithParams operation.

  • Defines the following in the page definition file:

    • A variable iterator for the attributes to use to access the variables (as opposed to a collection's iterator which is used for other forms).

    • A variableUsage variable for each parameter to hold the data values. These variables inherit the default value and UI control hints from the view object named bind variables to which they are bound. The variables are local, meaning they live only during a single request. Though they are carried across subsequent post-backs to the same form, they are forgotten (and re-initialized) when a user navigates to some other page.

    • An action binding for the operation that contains NamedData elements for each parameter. Each NamedData element is bound to a corresponding variable. These bindings allow the operation to access the value for the parameter upon execution.

    • Attribute bindings for the associated attributes.

Example 28-11 shows the executables and bindings in the page definition file that are created by dropping the SalesPeople collection's ExecuteWithParams operation on a page.

Example 28-11 Executable and Binding Properties for a Parameter Form

<executables>
  <variableIterator id="variables">
    <variableUsage DataControl="BackOfficeAppModuleDataControl"
                   Binds="SalesPeople.variablesMap.TitleIdBind"
                   Name="ExecuteWithParams_TitleIdBind" IsQueriable="false"/>
  </variableIterator>
  <iterator Binds="SalesPeople" RangeSize="25"  
            DataControl="BackOfficeAppModuleDataControl" 
            id="SalesPeopleIterator"/>
</executables>
<bindings>
  <action IterBinding="SalesPeopleIterator" id="ExecuteWithParams"
          RequiresUpdateModel="true"
          Action="executeWithParams">
    <NamedData NDName="TitleIdBind" NDType="java.lang.Integer" 
               NDValue="${bindings.ExecuteWithParams_TitleIdBind}"/>
  </action>
  <attributeValues IterBinding="variables" id="TitleIdBind">
    <AttrNames>
      <Item Value="ExecuteWithParams_TitleIdBind"/>
    </AttrNames>
  </attributeValues>
</bindings>

When you drop the collection that will be used to display the results of the parameter form, code is generated for a basic form, as described in Section 28.3.2, "What Happens When You Create a Form Using a Data Control Collection." In addition, if you use a table to display the results, the partialTriggers property on table is set to the command button in the parameter form.

28.7.3 What Happens at Runtime: How Parameters are Populated

When the page is rendered, the framework checks if the page is being rendered for the first time and if the exception list has any items. If both are false, then the framework executes the ExecuteWithParams action binding. This action binding executes the query, taking the values of the named data elements as values for the needed parameters.

28.8 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. Creating a basic input form is similar to creating an edit form, except that the input form also contains the CreateInsert operation, which causes a blank row to be inserted into the row set which the user can then populate using a form.

You can create a simple input form by dragging and dropping a collection and the appropriate operations from the Data Controls panel on to a page. However, you might need to employ a selection of other techniques to control the user workflow and insert other form processing logic. Such techniques may include:

The following section shows how to create a basic input form and provides information on a couple of variants.

28.8.1 How to Create an Input Form

Creating a basic input form involves creating an edit form and adding a command component for creating new records.

Before you begin:

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

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

You will need to complete this task:


Create an edit form as described in Section 28.6.1, "How to Create an Edit Form."

To create an input form:

  1. In the Data Controls panel, expand the node for the collection object on which the form is based.

  2. Expand the collection's Operations node and drag the CreateInsert operation to the edit form.

Note:

The CreateInsert operation is available only for data controls based on ADF Business Components application modules. If your data control is based on another business service, use the Create operation instead. For more information on the differences between the two, see Table 28-2.

28.8.1.1 Creating an Input Form Using a Bounded Task Flow

You can use a task flow to provide the workflow for input forms. Instead of using command components to create new objects, you use a method call activity in the task flow or a method in a managed bean. Instead of using a command component to commit changes, you use a task flow return activity.

For example, you can use a method call activity in a task flow to call a data control object's CreateInsert operation and then pass control to a view activity that displays a form where the user can enter the data.

To create an input form within a bounded task flow:

  1. Create a bounded task flow as described in Section 20.2, "Creating a Task Flow."

  2. In the Properties window, set the Transaction property to Always Begin New Transaction.

    For more information, see Section 24.3, "Managing Transactions in Task Flows."

  3. In the bounded task flow, add a method call activity.

    For more information, see Section 21.5, "Using Method Call Activities."

  4. From the Data Controls panel, drag the CreateInsert operation associated with the collection for which you are creating the form and drop it on the method activity.

  5. With the method call activity still selected, in the Properties window, enter a string for the fixed-outcome property. After dropping the CreateInsert operation on to the method call activity, this value is set to CreateInsert, but you may want to change it to something more specific.

  6. In the overview editor for the task flow, add a view activity that represents the page for the input form. For information on adding view activities, see Section 20.3, "Adding Activities to a Task Flow."

  7. Add a control flow case from the method activity to the view activity.

  8. With the control flow case still selected in the design editor, in the Properties window, make sure that the from-outcome property of the control flow case is the same as the value of the fixed-outcome property of the method activity set in Step 5.

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

  10. In the task flow, add a return activity. This return activity must execute the commit operation on the data control. For these procedures, see Section 21.7, "Using Task Flow Return Activities."

28.8.1.2 Using a Commit Button Instead of a Return Activity Within a Task Flow

Generally you should use a return activity to call the Commit operation. However, there might be cases where you need to use a command component for the Commit operation, such as when 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.

To create an input form that has a Commit button within the form:

  1. Create an input form as described in Section 28.8.1.1, "Creating an Input Form Using a Bounded Task Flow," but without setting the task flow return activity.

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

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

  4. In the Properties window, 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.

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

28.8.1.3 Creating an Input Form That Allows Multiple Entries in a Single Transaction

If you want the user to be able to create multiple entries before committing to the database, do the following:

To enable an input form to allow multiple entries in a single transaction:

  1. Create an input form as described in Section 28.8.1.1, "Creating an Input Form Using a Bounded Task Flow"

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

  3. Drag and drop a command component from the Components window 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.

28.8.2 What Happens When You Create an Input Form

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 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, button components.

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

When the CreateInsert button is clicked (or a method corresponding to that operation is called), the CreateInsert action binding is invoked, which executes the CreateInsertRow action, and a new blank instance for the collection is created.

Note:

When you use a task flow method activity to the call the CreateInsert operation, the method activity's binding container skips validation for required attributes during routing from the method activity to the view activity, allowing the blank instance to be displayed in the form on the page.

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

28.8.5 What You May Need to Know About Input Forms Backed By Stateless Services

If the data control on which your input form is based is a data control for a stateless business service, there is no built-in Commit operation for you to use to save changes back to the data source.

Instead, you need to use a custom method to save to the database. For more information, see Section 28.6.3, "What You May Need to Know About Working With Data Controls for Stateless Business Services."

28.9 Creating a Form with Dynamic Components

Instead of creating static databound forms where you provide tags for each component directly in the page, you can use a dynamic component to create forms where the binding metadata and the components used to display the bound content are determined at runtime.

This section provides information on creating databound dynamic forms. You can also use the dynamic component to create databound tables. For more information, see Section 29.5, "Creating a Table with Dynamic Components."

For more information on the dynamic form component, including how to create a custom data model, see "Determining Components at Runtime" in Developing Web User Interfaces with Oracle ADF Faces.

28.9.1 About Dynamic Components

ADF Faces provides the dynamicComponent tag that you can use to create model-driven forms and tables where the binding metadata and the tags used to display the bound content are determined at runtime.

The dynamic building of the bindings provides the following possibilities:

  • Enables you to create pages where the fields displayed and the ADF Faces components used to display them are determined by the data model. Any changes to the data model, such as additional columns or changed UI hints are reflected in the page without having to redesign the page. For more information about UI hints on view objects, see Section 5.13, "Defining UI Hints for View Objects."

  • Enables you to create pages based on polymorphic view objects, in which the fields available for a given record can differ depending on the record's base entity object. Since the fields to display are determined at runtime, you do not have to include fields in the page that may not apply to certain records or do coding in the view layer to adjust the fields that are displayed for a given record. For more information about building business components that work with multiple row types, see Chapter 7, "Defining Polymorphic View Objects."

You set display information using UI hints on a view object instead of configuring the information in the Create Form or Create Table dialog when 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.

Figure 28-13 shows a dynamic form at runtime that was designed by setting UI hints for attributes on the CustomerVO view object and then dropping the Customers data control collection as a dynamic form. Among the UI hints set were LABEL and DISPLAYHINT (the latter of which can be set to Hide in order to not include the given attribute in the dynamic form).

Figure 28-13 Dynamic Form Displays Based on Hints Set on the View Object

Form using CustomerVO, but with some attributes hidden

The following ADF Faces components can be rendered at runtime when you use af:dynamicComponent at design time:

  • af:inputText

  • af:inputDate

  • af:inputListOfValues

  • af:selectOneChoice

  • af:selectManyChoice

  • af:selectOneListbox

  • af:selectManyListbox

  • af:selectOneRadio

  • af:selectBooleanRadio

  • af:selectBooleanCheckbox

  • af:selectManyCheckbox

28.9.2 How to Create a Dynamic Form

To create a dynamic form, you drop a collection from the data controls panel as an ADF Form and specify that the fields be generated dynamically.

Before you begin:

It may be helpful to have an understanding of dynamic forms. For more information, see Section 28.9, "Creating a Form with Dynamic Components."

If you want to take advantage of dynamic forms to display records that contain varying attributes, you first need to have data objects that contain that capability. For information on creating view objects with this capability, see Section 7, "Defining Polymorphic View Objects."

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

You will need to complete these tasks:

To create a dynamic form:

  1. Set UI hints on the view object or data control structure definition file that corresponds to the collection for which you are creating the dynamic form.

    UI hints determine things such as the type of UI component to use to display the attribute, the label, the tooltip, whether the field should be automatically submitted, etc. You can also determine whether a given attribute is displayed or hidden. For procedures on creating UI hints, see Section 5.13, "Defining UI Hints for View Objects."

  2. Optionally, for the Category hint on each view object attribute, specify a category or click the New Category icon to create a new category.

    Any attributes that have the same category can be grouped together in dynamic forms that you create based on that view object.

  3. Optionally, for any categories that you have created in step 2, set the UI hints for the category's label and tooltip. These can be set in the UI Categories tab of the view object's overview editor.

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

  5. Drag the collection onto the page, and from the context menu, choose ADF Form.

  6. In the Create Form dialog, select the Fields Generated at Runtime checkbox.

  7. If you have specified any categories for attributes in step 2, select the Include Field Groups checkbox in order for the form to group the attributes according to those categories.

28.9.3 What Happens When You Create Dynamic Forms

When you drop a collection as a dynamic form on a page, the following things happen:

  • The page definition is populated with a variableIterator binding, an iterator binding to the iterator, and a tree value binding.

  • The JSF page is populated with one or more iterator and dynamicComponent tags. In addition, if the Include Field Groups option is selected, switcher and group tags are added.

28.9.3.1 Bindings Created for the Dynamic Form

The page definition file for a dynamic form contains the following executables and bindings:

  • variableIterator: an internal iterator that contains variables declared for the binding container.

  • iterator: the iterator binding for the collection. For more information on iterator bindings, see Section 28.2.2.1, "Iterator Bindings Created in the Page Definition File."

  • tree: the value binding for the attributes of the collection. Unlike a standard form, which has individual value bindings for each attribute set at design time, a dynamic form uses a single tree value binding to encompass the attributes that are exposed at runtime.

    Tree value bindings are also used for databound tables (both standard and dynamic). For more information, see Section 29.2.2.1, "Iterator and Value Bindings for Tables."

Example 28-12 shows the bindings for a page that contains a dynamic form component based on the Customers collection.

Example 28-12 Page Definition Code for a Dynamic Component

<executables>
  <variableIterator id="variables"/>
  <iterator Binds="SummitAppModuleDataControl.dataProvider.BackOfficeAM.Customers"
            DataControl="SummitAppModuleDataControl" RangeSize="25" id="CustomersIterator"/>
</executables>
<bindings>
  <tree IterBinding="CustomersIterator" id="Customers">
    <nodeDefinition DefName="oracle.summit.model.views.CustomerVO" Name="Customers0"/>
  </tree>
</bindings>

28.9.3.2 Tags Created for a Dynamic Form without Grouping

In the JSF page, JDeveloper inserts an iterator tag, within which it nests a dynamicComponent tag. The iterator tag loops through all of the attributes that are exposed by the collection at runtime and uses the dynamicComponent tag to render the appropriate component for each attribute on the page.

Example 28-13 shows the code that is generated when you drop the Customers data control object as a dynamic form (but do not select the Include Field Groups option).

Example 28-13 JSF Page Code for a Dynamic Form

<af:panelFormLayout id="pfl1">
    <af:iterator id="i1" value="#{bindings.Customers.attributesModel.attributes}"
                 var="attr">
        <af:dynamicComponent id="d2" attributeModel="#{attr}"/>
                   value="#{bindings[attr.containerName][attr.name].inputValue}"/>
    </af:iterator>
</af:panelFormLayout>

The value attribute of the iterator tag uses an EL expression that evaluates to the attributesModel.attributes property of the collection's tree binding. The attributesModel property is used to retrieve the data object's attributes and their metadata, such as component type, label, tooltip, and other properties of the real component to be rendered. The attributes property of attributesModel signifies that a flat (unhierarchical) list of displayable attributes and their metadata is provided.

The attributeModel attribute of the dynamicComponent tag is bound to the EL expression #{attr}, which references the variable that is defined in the iterator's var attribute and that serves as a pointer to the current attribute of the data control collection and its corresponding metadata. The EL expression for the dynamicComponent's value attribute also references the variable attr.

28.9.3.3 Tags Created for a Dynamic Form with Grouping

If you have selected the Include Field Groups checkbox in the Create Form dialog, the generated JSF page includes the switcher and group tags, in addition to the tags described in Section 28.9.3.2, "Tags Created for a Dynamic Form without Grouping."

The switcher tag is nested directly within a an iterator tag. Within the switcher tag are nested facet tags named GROUP and ATTRIBUTE. The GROUP facet contains a group tag, within which is an outputText tag to display the group name and an iterator tag, which contains a dynamicComponent tag. The ATTRIBUTE facet only contains a dynamicComponent tag.

For each attribute that the high-level iterator iterates over, the switcher dynamically determines whether to render a group or a component for the individual attribute. If it renders a group, the iterator within the group then is used to render the components for the attributes within that group.

Example 28-14 shows the code that is generated if you create a dynamic form based on the Customers collection and choose to include field groups.

Example 28-14 JSF Page Code for a Dynamic Form With Attribute Groups

<af:panelFormLayout id="pfl1">
    <af:iterator id="i1"
              value="#{bindings.Customers.attributesModel.hierarchicalAttributes}"
              var="attr">
        <af:switcher id="sw1" facetName="#{attr.descriptorType}"
                     defaultFacet="ATTRIBUTE">
            <f:facet name="GROUP">
                <af:group title="#{attr.label}" id="g1">
                    <af:outputText value="#{attr.name}" id="ot1"/>
                    <af:iterator id="gi1" value="#{attr.descriptors}"
                                 var="nestedAttr">
                        <af:dynamicComponent id="gd1"
                                             attributeModel="#{nestedAttr}"/>
                    </af:iterator>
                </af:group>
            </f:facet>
            <f:facet name="ATTRIBUTE">
                <af:dynamicComponent id="ad1" attributeModel="#{attr}"/>
            </f:facet>
        </af:switcher>
    </af:iterator>
</af:panelFormLayout>

The value attribute of the iterator tag uses an EL expression that evaluates to the attributesModel.hierarchicalAttributes property of the collection's tree binding. The attributesModel property is used to retrieve the data object's attributes and their metadata, such as component type, label, tooltip, and other properties of the real component to be rendered. The hierarchicalAttributes property signifies that a hierarchical list of displayable attributes and their metadata is provided, including any categories that have been set for any attributes in the UI hints.

The attributeModel attribute of the dynamicComponent tag is set to the EL expression #{attr}, which references the variable that is defined in the iterator's var attribute and that serves as a pointer to the current attribute (or category) of the data control collection and its corresponding metadata.

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

At runtime, the iterator iterates over the set of attributes and instantiates a dynamicComponent for each attribute. The dynamic component uses its attributeModel property to obtain information from the iterator about the current attribute, such as label and control type. Each dynamicComponent then renders a component based on the metadata that is returned for the attribute.

If the DISPLAYHINT UI hint for an attribute is set to Hide, no component for the attribute is rendered.

If the dynamic form is created from a data control object that is based on a polymorphic view object, the rendered components depend on the row type for the currently selected record.

28.9.5 How to Apply Validators and Converters to a Dynamic Component

By default, standard ADF Faces converters and validators are applied to the components generated at runtime when using dynamic components. For example, converterDateTime converters are applied to components based on attributes of type TimeStamp.

If you need to add more specific validation or conversion to a component, you can do so by adding ADF Faces validator and converter tags to the source for the dynamic component and use the tags' disabled attribute to determine on which attributes the validators and converters are applied.

Before you begin:

It may be helpful to have an understanding of dynamic forms. For more information, see Section 28.9, "Creating a Form with Dynamic Components."

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

You will need to complete this task:


Create a dynamic form as shown in Section 28.9.2, "How to Create a Dynamic Form" or a dynamic table as shown in Section 29.5.1, "How to Create a Dynamic Table."

To manually insert an ADF Faces validator or converter into a dynamic form:

  1. Open the page containing the dynamic component in the source editor.

  2. Within the <af:dynamicComponent> tag, insert any validator and converter components that you want to use.

  3. Within the each validator and converter tag, insert the disabled attribute and bind it to an EL expression that disables the tag for all attributes except for those to which you want to apply it.

    For example, the following expression would enable a validator only for the Hiredate attribute:

    #{attr.name == 'Hiredate' ? false : true}
    

Example 28-15 shows a dynamic component with two validators and two converters applied.

Example 28-15 Validators and Converters Applied to a Dynamic Component

<af:panelFormLayout id="pfl1">
  <af:iterator id="i1" value="#{bindings.EmpVO1.attributesModel.attributes}" 
                       var="attr">
    <af:dynamicComponent 
                  value="#{bindings[attr.containerName][attr.name].inputValue}" 
                  attributeModel="#{attr}" id="dc1"/>
      <af:convertDateTime disabled="#{attr.name == 'Hiredate' ? false : true}"
                          pattern="yyyy/MM/dd"/>
      <af:convertNumber disabled="#{attr.name == 'Sal' ? false : true}" 
                        pattern="#,###,###" />
      <af:validateLength disabled="#{attr.name == 'Job' ? false : true}"
                         maximum="10" hintMaximum="maxmum length is 10"/>
      <af:validateLongRange disabled="#{attr.name == 'Sal' ? false : true}" 
                            minimum="1000"/>
    </af:dynamicComponent>
  </af:iterator>
</af:panelFormLayout>

28.9.6 What You May Need to Know About Mixing Dynamic Components with Static Components

When you create a dynamic form, you essentially create a block of components that are rendered dynamically. It is possible place static components before and after that block of components, but you can not intersperse static components within that block.

Example 28-16 illustrates the granularity of mixing static and dynamic components that is possible. It consists of three group tags, the first and third of which contain static content and the second of which contains an iterator tag with a nested dynamicComponent tag.

Example 28-16 Mixing Static Content with Dynamic Content

<af:group title="static before dynamic" id="g1">
    <af:separator id="sp2"/>
    <af:inputText value="#{bindings.Empno.inputValue}" label="Static Empno"
                  required="#{bindings.Empno.hints.mandatory}"
                  columns="#{bindings.Empno.hints.displayWidth}"
                  maximumLength="#{bindings.Empno.hints.precision}"
                  shortDesc="#{bindings.Empno.hints.tooltip}" id="it1">
        <f:validator binding="#{bindings.Empno.validator}"/>
        <af:convertNumber groupingUsed="false" 
                          pattern="#{bindings.Empno.format}"/>
    </af:inputText>
</af:group>
<af:group title="dynamic part" id="g2">
    <af:separator id="sp3"/>
    <af:panelFormLayout id="pfl1">
        <af:iterator id="i1" value="#{bindings.EmpVO1.attributesModel.attributes}"
                     var="attr">
            <af:dynamicComponent 
                     value="#{bindings[attr.containerName][attr.name].inputValue}" 
                     id="dc1" attributeModel="#{attr}"/>
        </af:iterator>
    </af:panelFormLayout>
</af:group>
<af:group title="static after dynamic" id="g3">
    <af:separator id="sp4"/>
    <af:inputText value="#{bindings.Ename.inputValue}" label="Static Ename"
                  required="#{bindings.Ename.hints.mandatory}"
                  columns="#{bindings.Ename.hints.displayWidth}"
                  maximumLength="#{bindings.Ename.hints.precision}"
                  shortDesc="#{bindings.Ename.hints.tooltip}" id="it2">
        <f:validator binding="#{bindings.Ename.validator}"/>
    </af:inputText>
</af:group>
<af:button text="Back" id="cbb1" action="back"/>

28.9.7 How to Programmatically Set Dynamic Component Behavior

If you have any custom processing that you need to do to determine how the dynamic component is rendered, you can do so in a managed bean and then bind the dynamic component's attributeModel property to the appropriate bean method.

Before you begin:

It may be helpful to have an understanding of dynamic forms. For more information, see Section 28.9, "Creating a Form with Dynamic Components."

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

You will need to complete this task:


Create a dynamic form as shown in Section 28.9.2, "How to Create a Dynamic Form" or a dynamic table as shown in Section 29.5.1, "How to Create a Dynamic Table."

To programmatically set a dynamic component's behavior:

  1. In the UI project that contains the dynamic component, create a Java class that extends the oracle.adf.view.rich.model.BaseAttributeDescriptor class.

    Example 28-17 shows a sample class that adds a method to apply a custom style to the label for the Sal attribute.

    Example 28-17 Custom Implementation of BaseAttributeDescriptor

    public class CustomizedDescriptor extends BaseAttributeDescriptor
    {
      public CustomizedDescriptor(BaseAttributeDescriptor base)
      {
        _base = base;
      }
     
      public Object getLabelStyle()
      {
        if (getName().equals("Sal"))
          return "color:red; font-weight:bold";
        else
          return null;
      }
    
  2. Create a managed bean for the page. For more information, see Section 26.4, "Using a Managed Bean in a Fusion Web Application."

  3. In the managed bean, create a method that returns an instance of the custom descriptor that you created in step 1. Example 28-18 shows such a method.

    Example 28-18 Managed Bean Method That Returns a Custom Attribute Descriptor

    public CustomizedDescriptor getCustomizedAttributes(String attrName)
      {
      // create value expression for "#{attrName}" and evaluate it to get object
      // of "attr"
        BaseAttributeDescriptor attrMetadata = null;
        Class klass = null;
     
        try
        {
          klass = ClassLoaderUtils.loadClass("oracle.adf.view.rich.model.BaseAttributeDescriptor");
        }
        catch (ClassNotFoundException e)
        {
          throw new RuntimeException("Can not find class oracle.adf.view.rich.model.BaseAttributeDescriptor");
        }
     
        FacesContext facesContext = FacesContext.getCurrentInstance();
        ELContext elContext = facesContext.getELContext();
        ValueExpression valueExpression = createValueExpression(attrName, klass);
     
        if (valueExpression != null)
          attrMetadata = (BaseAttributeDescriptor)valueExpression.getValue(elContext);
     
        return new CustomizedDescriptor(attrMetadata);
      }
    
  4. In the source editor for the page containing the dynamic component, bind the dynamic component's attributeModel property to the managed bean method that returns the customized attribute descriptor.

    Example 28-19 shows a dynamicComponent tag where its attributeModel attribute has been set to an EL expression that references the getCustomizedAttributes method of the attributeCustomBean managed bean.

    Example 28-19 attributeModel Attribute Bound to a Managed Bean

    <af:panelFormLayout id="pfl1">
      <af:iterator id="i1" value="#{bindings.EmpVO1.attributesModel.attributes}"
                   var="attr">
        <af:dynamicComponent value="#{bindings[attr.containerName][attr.name].inputValue}" attributeModel="#{attributeCustomBean.getCustomizedAttributes('attr')}" />
      </af:iterator>
    </af:panelFormLayout>
    

28.9.8 How to Access a Dynamic Component Programmatically

If you need to access a dynamic component instance programmatically to make changes based on a user action, you can do so by using a managed bean.

Before you begin:

It may be helpful to have an understanding of dynamic forms. For more information, see Section 28.9, "Creating a Form with Dynamic Components."

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

You will need to complete this task:


Create a dynamic form as shown in Section 28.9.2, "How to Create a Dynamic Form" or a dynamic table as shown in Section 29.5.1, "How to Create a Dynamic Table."

To programmatically access a dynamic component's binding instance:

  1. Create a managed bean method that identifies dynamic component, casts the component to RichDynamicComponent, and then applies any changes.

    For more information, see Section 26.4, "Using a Managed Bean in a Fusion Web Application."

  2. In the page containing the dynamic component, add a command component to the page and bind its actionListener property to the managed bean method.

Example 28-20 shows a managed bean method that changes the label style for a dynamic component.

Example 28-20 Managed Bean Code to Access a Dynamic Component's Binding Instance

public void changeLabelColor (ActionEvent event)
  {
    UIComponent component = event.getComponent().getParent();
    component = component.findComponent("pfl1");
 
    while(component != null)
    {
      if(component.getId().equals("it1"))
      {
        RichDynamicComponent rdc = (RichDynamicComponent)component;
        rdc.setLabelStyle("color:red");
        break;
      }
      else
        component = component.getChildren().get(0);
    }
  }

28.9.9 How to Access a Dynamic Component's Binding Instance Programmatically

If you need to access a runtime binding instance of a dynamic component programmatically, you can do so using a managed bean.

Before you begin:

It may be helpful to have an understanding of dynamic forms. For more information, see Section 28.9, "Creating a Form with Dynamic Components."

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

You will need to complete this task:


Create a dynamic form as shown in Section 28.9.2, "How to Create a Dynamic Form" or a dynamic table as shown in Section 29.5.1, "How to Create a Dynamic Table."

To access a dynamic component's binding instance programmatically:

  1. Create a managed bean method that accesses the binding container through the FacesContext, gets the AttributesModel, and then applies the desired business logic.

    For more information, see Section 26.4, "Using a Managed Bean in a Fusion Web Application."

  2. In the page containing the dynamic component, add a command component to the page and bind its actionListener property to the managed bean method.

Example 28-21 illustrates a managed bean method that will set the DeptNo value of the current row to 9999.

Example 28-21 Managed Bean Method That Accesses a Dynamic Component's Binding Context

public void setValueThroughBinding(ActionEvent event)
  {
    // get binding container
    FacesContext facesContext = FacesContext.getCurrentInstance();
    ELContext elContext = facesContext.getELContext();
    ValueExpression valueExpression = createValueExpression("bindings", 
                                      DCBindingContainer.class);
    DCBindingContainer binding = (DCBindingContainer) 
                                 valueExpression.getValue(elContext);
 
    // get AttributesModel and attribute metadata list
    valueExpression = createValueExpression("bindings.EmpVO1.attributesModel", 
                      AttributesModel.class);
    AttributesModel attributesModel = (AttributesModel) 
                                      valueExpression.getValue(elContext);
    List<BaseAttributeDescriptor> attrList = attributesModel.getAttributes();
 
    // get AttributeMetadata for "Empno"
    BaseAttributeDescriptor deptNoAttributeBase = null;
    FacesAttributeDescriptor deptNoAttribute = null;
    for (BaseAttributeDescriptor attrDescriptor: attrList)
    {
      if ("Comm".equals(attrDescriptor.getName()))
      {
        deptNoAttributeBase = attrDescriptor;
        break;
      }
    }
 
    deptNoAttribute = (FacesAttributeDescriptor)deptNoAttributeBase;
    if (deptNoAttribute == null || deptNoAttribute.getContainerName() == null)
    {
      System.out.println("AttributesModel of Empno or its model name"); 
      System.out.println("can not be found.");
      return;
    }
 
    // get Deptno attribute value binding, set input value
    JUFormBinding fb = (JUFormBinding) binding.findExecutableBinding((String)
                                        deptNoAttribute.getContainerName());
    JUCtrlValueBinding valueBinding = (JUCtrlValueBinding)
                                  fb.getControlBinding(deptNoAttribute.getName());
    valueBinding.setInputValue(Integer.valueOf(9999));
 
    System.out.println("Found JUCtrlValueBinding " + deptNoAttribute.getName()");
    System.out.println("set its value to 9999.");
  }

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

28.10.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 Properties window to change or delete bindings, or to change the label displayed for a component.

Before you begin:

It may be helpful to have a general understanding of working with UI components after they have been generated. For more information, see Section 28.10, "Modifying the UI Components and Bindings on a Form."

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

You will need to complete these tasks:

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 Properties window. 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 Properties window:

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

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