Oracle® Fusion Middleware Fusion Developer's Guide for Oracle Application Development Framework 11g Release 1 (11.1.1.5.0) Part Number B31974-10 |
|
|
View PDF |
This chapter describes how to use the Data Controls panel to create databound forms using ADF Faces components.
This chapter includes the following sections:
Section 22.1, "Introduction to Creating a Basic Databound Page"
Section 22.7, "Using a Dynamic Form to Determine Data to Display at Runtime"
Section 22.8, "Modifying the UI Components and Bindings on a Form"
You can create UI pages that allow you to display and collect information using data controls created for your business services. For example, using the Data Controls panel, you can drag an attribute for an item, and then choose to display the value either as read-only text or as an input text field with a label. JDeveloper creates all the necessary JSF tag and binding code needed to display and update the associated data. For more information about the Data Controls panel and the declarative binding experience, see Chapter 12, "Using ADF Model in a Fusion Web Application."
Instead of having to drop individual attributes, JDeveloper allows you to drop all attributes for an object at once as a form. The actual UI components that make up the form depend on the type of form dropped. You can create forms that display values, forms that allow users to edit values, and forms that collect values (input forms).
For example, the StoreFront module contains a page that allows users to register information about themselves, as shown in Figure 22-1. This form was created by dragging and dropping the CustomerRegistration
collection from the Data Controls panel.
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.
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.
To create a text field that can display or update an attribute, you drag and drop an attribute of a collection from the Data Controls panel.
To create a bound text field:
From the Data Controls panel, select an attribute for a collection. For a description of the icons that represent attributes and other objects in the Data Controls panel, see Section 12.3, "Using the Data Controls Panel."
For example, Figure 22-2 shows the FirstName
attribute under the CustomerRegistration
collection of the StoreServiceAMDataControl
data control in the StoreFront module. This is the attribute to drop to display or enter the customer's first name.
Drag the attribute onto the page, and from the context menu choose the type of widget to display or collect the attribute value. For an attribute, you are given the following choices:
Text:
ADF Input Text w/ Label: Creates an ADF Faces inputText
component with a nested validator
component. The label
attribute is populated.
Tip:
For more information about validators and other attributes of theinputText
component, see the "Using Input Components and Defining Forms" chapter of the Oracle Fusion Middleware Web User Interface Developer's Guide for Oracle Application Development Framework.ADF Input Text: Creates an ADF Faces inputText
component with a nested validator
component. The label
attribute is not populated.
ADF Output Text w/ Label: Creates a panelLabelAndMessage
component that holds an ADF Faces outputText
component. The label
attribute on the panelLabelAndMessage
component is populated.
ADF Output Text: Creates an ADF Faces outputText
component. No label is created.
ADF Output Formatted w/Label: Same as ADF Output Text w/Label, but uses an outputFormatted
component instead of an outputText
component. The outputFormatted
component allows you to add a limited amount of HTML formatting. For more information, see the "Displaying Output Text and Formatted Output Text" section of the Oracle Fusion Middleware Web User Interface Developer's Guide for Oracle Application Development Framework
ADF Output Formatted: Same as ADF Output Formatted w/Label, but without the label.
ADF Label: An ADF Faces outputLabel
component.
List of Values: Creates ADF LOV lists. For more information about how these lists work, see Section 5.12, "Working with List of Values (LOV) in View Object Attributes." For more information about using the lists on a JSF page, see Section 25.3, "Creating a Selection List."
Single selections: Creates single selection lists. For more information about creating lists on a JSF page, see Section 25.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 Attribute Control Hints for View Objects."For the purposes of this chapter, only the text components (and not the lists) will be discussed.
When you drag an attribute onto a JSF page and drop it as a UI component, among other things, a page definition file is created for the page (if one does not already exist). For a complete account of what happens when you drag an attribute onto a page, see Section 12.3.2, "What Happens When You Use the Data Controls Panel." Bindings for the iterator and attributes are created and added to the page definition file. Additionally, the necessary JSPX page code for the UI component is added to the JSF page.
Whenever you create UI components on a page by dropping an item that is part of a collection from the Data Controls panel (or you drop the whole collection as a form or table), JDeveloper creates an iterator binding if it does not already exist. An iterator binding references an iterator for the data collection, which facilitates iterating over its data objects. It also manages currency and state for the data objects in the collection. An iterator binding does not actually access the data. Instead, it simply exposes the object that can access the data and it specifies the current data object in the collection. Other bindings then refer to the iterator binding in order to return data for the current object or to perform an action on the object's data. Note that the iterator binding is not an iterator. It is a binding to an iterator. In the case of ADF Business Components, the actual iterator is the default row set iterator for the default row set of the view object instance in the application module's data model.
For example, if you drop the FirstName
attribute under the CustomerRegistration
collection, JDeveloper creates an iterator binding for the
collection.
CustomerRegistration
Tip:
There is one iterator binding created for each collection. This means that when you drop two attributes from the same collection (or drop the collection twice), they use the same binding. This is fine, unless you need the binding to behave differently for the different components. In that case, you will need to manually create separate iterator bindings.The iterator binding's rangeSize
attribute determines how many rows of data are fetched from a data control each time the iterator binding is accessed. This attribute gives you a relative set of 1-n rows positioned at some absolute starting location in the overall row set. By default, it the attribute set to 25
. For more information about using this attribute, see Section 22.4.2.2, "Iterator RangeSize Attribute." Example 22-1 shows the iterator binding created when you drop an attribute from the CustomerRegistration
collection.
Example 22-1 Page Definition Code for an Iterator Binding for an Attribute Dropped from a Collection
<executables> <iterator Binds="CustomerRegistration" RangeSize="25" DataControl="StoreServiceAMDataControl" id="CustomerRegistrationIterator"/> </executables>
For information regarding the iterator binding element attributes, see Appendix B, "Oracle ADF Binding Properties."
This metadata allows the ADF binding container to access the attribute values. Because the iterator binding is an executable, by default, it is invoked when the page is loaded, thereby allowing the iterator to access and iterate over the CustomerRegistration
collection. This means that the iterator will manage all the CustomerRegistration
objects in the collection, including determining the current CustomerRegistration
or range of CustomerRegistration
objects.
When you drop an attribute from the Data Controls panel, JDeveloper creates an attribute binding that is used to bind the UI component to the attribute's value. This type of binding presents the value of an attribute for a single object in the current row in the collection. Value bindings can be used both to display and to collect attribute values.
For example, if you drop the PrincipalName
attribute under the CustomerRegistration
collection as an ADF Output Text w/Label widget onto a page, JDeveloper creates an attribute binding for the PrincipalName
attribute. This allows the binding to access the attribute value of the current record. Example 22-2 shows the attribute binding for PrincipalName
created when you drop the attribute from the CustomerRegistration
collection. Note that the attribute value references the iterator named CustomerRegistration
Iterator
.
Example 22-2 Page Definition Code for an Attribute Binding
<bindings> ... <attributeValues IterBinding="CustomerRegistrationIterator" id="PrincipalName"> <AttrNames> <Item Value="PrincipalName"/> </AttrNames> </attributeValues> </bindings>
For information regarding the attribute binding element properties, see Appendix B, "Oracle ADF Binding Properties."
When you create a text field by dropping an attribute from the Data Controls panel, JDeveloper creates the UI component associated with the widget dropped by writing the corresponding tag to the JSF page.
For example, when you drop the PrincipalName
attribute as an Output Text w/Label widget, JDeveloper inserts the tags for a panelLabelAndMessage
component and an outputText
component. It creates an EL expression that binds the label
attribute of the panelLabelAndMessage
component to the label
property of hints created for the PrincipalName
's binding. This expression evaluates to the label hint set on the view object (for more information about hints, see Section 5.13, "Defining Attribute Control Hints for View Objects"). It creates another expression that binds the outputText
component's value
attribute to the inputValue
property of the PrincipalName
binding, which evaluates to the value of the PrincipalName
attribute for the current row. An ID is also automatically generated for both components.
Tip:
JDeveloper automatically generates IDs for all ADF Faces components. You can override these values as needed.Example 22-3 shows the code generated on the JSF page when you drop the PrincipalName
attribute as an Output Text w/Label widget.
Example 22-3 JSF Page Code for an Attribute Dropped as an Output Text w/Label
<af:panelLabelAndMessage label="#{bindings.PrincipalName.hints.label}" id="plam1"> <af:outputText value="#{bindings.PrincipalName.inputValue}" id="ot1"/> </af:panelLabelAndMessage>
If instead you drop the PrincipalName
attribute as an Input Text w/Label widget, JDeveloper creates an inputText
component. As Example 22-4 shows similar to the output text component, the value is bound to the inputValue
property of the PrincipalName
binding. Additionally, the following properties are also set:
label
: Bound to the label
property of the control hint set on the object.
required
: Bound to the mandatory
property of the control hint.
columns
: Bound to the displayWidth
property of the control hint, which determines how wide the text box will be.
maximumLength
: Bound to the precision property of the control hint. This control hint property determines the maximum number of characters per line that can be entered into the field.
In addition, JDeveloper adds a validator component.
Example 22-4 JSF Page Code for an Attribute Dropped as an Input Text w/Label
<af:inputText value="#{bindings.PrincipalName.inputValue}" label="#{bindings.PrincipalName.hints.label}" required="#{bindings.PrincipalName.hints.mandatory}" columns="#{bindings.PrincipalName.hints.displayWidth}" maximumLength="#{bindings.PrincipalName.hints.precision}"> shortDesc="#{bindings.PrincipalName.hints.tooltip}" id="it1"> <f:validator binding="#{bindings.PrincipalName.validator}"/> </af:inputText>
You can change any of these values to suit your needs. For example, the mandatory
control hint on the view object is set to false
by default, which means that the required attribute on the component will evaluate to false
as well. You can override this value by setting the required
attribute on the component to true
. If you decide that all instances of the attribute should be mandatory, then you can change the control hint on the view object, and all instances will then be required. For more information about these properties, see Appendix B, "Oracle ADF Binding Properties."
Instead of dropping each of the individual attributes of a collection to create a form, you can a complete form that displays or collects data for all the attributes on an object.
For example, you could create a page that displays basic information about registered users in the StoreFront module by dragging and dropping the CustomerInfoVO
1 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 22.5, "Creating a Form to Edit an Existing Record." For information about creating forms that allow users to create a new object for the collection, see Section 22.6, "Creating an Input Form". You can also create search forms. For more information, see Chapter 27, "Creating ADF Databound Search Forms."
To create a form using a data control, you bind the UI components to the attributes on the corresponding object in the data control. JDeveloper allows you to do this declaratively by dragging and dropping a collection or a structured attribute from the Data Controls panel.
To create a basic form:
From the Data Controls panel, select the collection that represents the data you wish to display. Figure 22-3 shows the CustomerInfoVO
1 collection for the StoreServiceAMDataControl
data control.
Drag the collection onto the page, and from the context menu choose the type of form that will be used to display or collect data for the object. For a form, you are given the following choices:
ADF Form: Launches the Edit Form Fields dialog that allows you to select individual attributes instead of having JDeveloper create a field for every attribute by default. It also allows you to select the label and UI component used for each attribute. By default, ADF inputText
components are used for most attributes. Each inputText
component has the label
attribute populated.
Attributes that are dates use the InputDate
component. Additionally, if a control type control hint has been created for an attribute, or if the attribute has been configured to be a list, then the component set by the hint is used instead. InputText
components contain a validator tag that allows you to set up validation for the attribute, and if the attribute is a number or a date, a converter is also included.
Tip:
For more information about validators, converters, and other attributes of theinputText
component, see the "Using Input Components and Defining Forms" chapter of the Oracle Fusion Middleware Web User Interface Developer's Guide for Oracle Application Development Framework.ADF Read-Only Form: Same as the ADF Form, but only read-only outputText
components are used. Since the form is meant to display data, no validator
tags are added (converters are included). Attributes of type Date
use the outputText
component when in a read-only form. All components are placed inside panelLabelAndMessage
components, which have the label
attribute populated, and are placed inside a panelFormLayout
component.
ADF Search Form: Creates a form that can be used to execute a Query-by-Example (QBE) search. For more information, see Chapter 27, "Creating ADF Databound Search Forms."
In the Edit Form Fields dialog, configure your form.
You can elect to include navigational controls that allow users to navigate through all the data objects in the collection. For more information, see Section 22.4, "Incorporating Range Navigation into Forms." You can also include a Submit button used to submit the form. This button submits the HTML form and applies the data in the form to the bindings as part of the JSF/ADF page lifecycle. For additional help in using the dialog, click Help. All UI components are placed inside a panelFormLayout
component.
If you are building a form that allows users to update data, you now need to drag and drop an operation that will perform the update. For more information, see Section 22.5, "Creating a Form to Edit an Existing Record."
Dropping an object as a form from the Data Controls panel has the same effect as dropping a single attribute, except that multiple attribute bindings and associated UI components are created. The attributes on the UI components (such as value
) are bound to properties on that attribute's binding object (such as inputValue
) or to the values of control hints set on the corresponding business object. Example 22-5 shows some of the code generated on the JSF page when you drop the CustomerInfoVO
1 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 22-5 Code on a JSF Page for an Input Form
<af:panelFormLayout id="pfl1"> <af:inputText value="#{bindings.PersonId.inputValue}" label="#{bindings.PersonId.hints.label}" required="#{bindings.PersonId.hints.mandatory}" columns="#{bindings.PersonId.hints.displayWidth}" maximumLength="#{bindings.PersonId.hints.precision}" shortDesc="#{bindings.PersonId.hints.tooltip}" id="it2"> <f:validator binding="#{bindings.PersonId.validator}"/> </af:inputText> <af:inputText value="#{bindings.FirstName.inputValue}" label="#{bindings.FirstName.hints.label}" required="#{bindings.FirstName.hints.mandatory}" columns="#{bindings.FirstName.hints.displayWidth}" maximumLength="#{bindings.FirstName.hints.precision}" shortDesc="#{bindings.FirstName.hints.tooltip}" id="it1"> <f:validator binding="#{bindings.FirstName.validator}"/> </af:inputText> <af:inputText value="#{bindings.LastName.inputValue}" label="#{bindings.LastName.hints.label}" required="#{bindings.LastName.hints.mandatory}" columns="#{bindings.LastName.hints.displayWidth}" maximumLength="#{bindings.LastName.hints.precision}" shortDesc="#{bindings.LastName.hints.tooltip}" id="it7"> <f:validator binding="#{bindings.LastName.validator}"/> </af:inputText> . . . </af:panelFormLayout>
Note:
For information regarding the validator and converter tags, see the "Validating and Converting Input" chapter of the Oracle Fusion Middleware Web User Interface Developer's Guide for Oracle Application Development Framework.When you choose to create an input form using an object that contains a defined list of values (LOV), then a selectOneChoice
component is created instead of an inputText
component. For example, the PersonsVO
view object contains a defined LOVs for the Title
, Gender
, MaritalStatusCode
, and PersonTypeCode
attributes. When you drop the Persons
data control object as an ADF Form, instead of as an empty input text field, a dropdown list showing all values is created. For more information about how these lists work, see Section 5.12, "Working with List of Values (LOV) in View Object Attributes." For more information about using the lists on a JSF page, see Section 25.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.When you create an ADF Form, if you elect to include navigational controls, JDeveloper includes ADF Faces command components bound to existing navigational logic on the data control. This built-in logic allows the user to navigate through all the data objects in the collection. For example,Figure 22-4 shows a form that would be created if you drag the CustomerInfoVO
1 collection and drop it as an ADF Form that uses navigation.
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.
To manually add navigation buttons:
From the Data Controls panel, select the operation associated with the collection of objects on which you wish the operation to execute, and drag it onto the JSF page.
For example, if you want to navigate through a collection of persons, you would drag the Next operation associated with the Persons
collection. Figure 22-5 shows the operations associated with the CustomerInfoVO1
collection.
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.When you drop any operation as a command component, JDeveloper:
Defines an action binding in the page definition file for the associated operations
Configures the iterator binding to use partial page rendering for the collection
Inserts code in the JSF page for the command components
Action bindings execute business logic. For example, they can invoke built-in methods on the action binding object. These built-in methods operate on the iterator or on the data control itself, and are represented as operations in the Data Controls panel. JDeveloper provides navigation operations that allow users to navigate forward, backwards, to the last object in the collection, and to the first object.
Like value bindings, action bindings for operations contain a reference to the iterator binding when the action binding is bound to one of the iterator-level actions, such as Next
or Previous
. These types of actions are performed by the iterator, which determines the current object and can therefore determine the correct object to display when a navigation buttons is clicked. Action bindings to other than iterator-level actions, for example for a custom method on an application module, or for the commit or rollback operations, will not contain this reference.
Action bindings use the RequiresUpdateModel
property, which determines whether or not the model needs to be updated before the action is executed. In the case of navigation operations, by default this property is set to true
, which means that any changes made at the view layer must be moved to the model before navigation can occur. Example 22-6 shows the action bindings for the navigation operations.
Example 22-6 Page Definition Code for an Operation Action Binding
<action IterBinding="CustomerInfoVO1Iterator" id="First" RequiresUpdateModel="true" Action="first"/> <action IterBinding="CustomerInfoVO1Iterator" id="Previous" RequiresUpdateModel="true" Action="previous"/> <action IterBinding="CustomerInfoVO1Iterator" id="Next" RequiresUpdateModel="true" Action="next"/> <action IterBinding="CustomerInfoVO1Iterator" id="Last" RequiresUpdateModel="true" Action="last"/>
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 22-7 shows the default range size for the CustomerInfoVO
iterator.
Example 22-7 RangeSize Attribute for an Iterator
<iterator Binds="CustomerInfoVO" RangeSize="25"
DataControl="StoreServiceAMDataControl"
id="CustomerInfoVO1Iterator"
ChangeEventPolicy="ppr"/>
Note:
ThisrangeSize
attribute is not the same as the rows
attribute on a table component. For more information, see Table 23-1, "ADF Faces Table Attributes and Populated Values".By default, the rangeSize
attribute is set to 25
. This means that a user can view 25 objects, navigating back and forth between them, without needing to access the data source. The iterator keeps track of the current object. Once a user clicks a button that requires a new range (for example, clicking the Next button on object number 25), the binding object executes its associated method against the iterator, and the iterator retrieves another set of 25 records. The bindings then work with that set. You can change this setting as needed. You can set it to -1
to have the full record set returned.
Note:
When you create a navigateable form using the Data Controls panel, theCacheResults
property on the associated iterator is set to true
. This ensures that the iterator's state, including currency information, is cached between requests, allowing it to determine the current object. If this property is set to false
, navigation will not work.Table 22-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 22.4.4, "What Happens at Runtime: How Action Events and Action Listeners Work."
Table 22-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. |
When you create command components using navigation operations, the command components are placed in a panelGroupLayout
component. JDeveloper creates an EL expression that binds a navigational command button's actionListener
attribute to the execute
property of the action binding for the given operation.
At runtime an action binding will be an instance of the FacesCtrlActionBinding
class, which extends the core JUCtrlActionBinding
implementation class. The FacesCtrlActionBinding
class adds the following methods:
public void execute(ActionEvent event)
: This is the method that is referenced in the actionListener
property, for example #{bindings.First.execute}
.
This expression causes the binding's operation to be invoked on the iterator when a user clicks the button. For example, the First command button's actionListener
attribute is bound to the execute
method on the First
action binding.
public String outcome()
: This can be referenced in an Action
property, for example #{bindings.Next.outcome}
.
This can be used for the result of a method action binding (once converted to a String
) as a JSF navigation outcome to determine the next page to navigate to.
Note:
Using the outcome method on the action binding implies tying the view-controller layer too tightly to the model, so it should be rarely used.Every action binding for an operation has an enabled
boolean property that Oracle ADF sets to false
when the operation should not be invoked. By default, JDeveloper binds the UI component's disabled
attribute to this value to determine whether or not the component should be enabled. For example, the UI component for the First button has the following as the value for its disabled
attribute:
#{!bindings.First.enabled}
This expression evaluates to true
whenever the binding is not enabled, that is, when operation should not be invoked, thereby disabling the button. In this example, because the framework will set the enabled
property on the binding to false
whenever the first record is being shown, the First button will automatically be disabled because its disabled
attribute is set to be true
whenever enabled
is False
. For more information about the enabled
property, see Appendix B, "Oracle ADF Binding Properties."
Example 22-8 shows the code generated on the JSF page for navigation operation buttons. For more information about the partialSubmit
attribute on the button, see Section 22.4.3, "What You May Need to Know About Automatic Partial Page Rendering."
Example 22-8 JSF Code for Navigation Buttons Bound to ADF Operations
<f:facet name="footer"> <af:panelGroupLayout> <af:commandButton actionListener="#{bindings.First.execute}" text="First" disabled="#{!bindings.First.enabled}" partialSubmit="true" id="cb1"/> <af:commandButton actionListener="#{bindings.Previous.execute}" text="Previous" disabled="#{!bindings.Previous.enabled}" partialSubmit="true" id="cb2"/> <af:commandButton actionListener="#{bindings.Next.execute}" text="Next" disabled="#{!bindings.Next.enabled}" partialSubmit="true" id="cb3"/> <af:commandButton actionListener="#{bindings.Last.execute}" text="Last" disabled="#{!bindings.Last.enabled}" partialSubmit="true" id="cb4"/> </af:panelGroupLayoutr> </f:facet>
When you create a form with navigational controls, JDeveloper configures the iterator binding to automatically use partial page rendering (PPR). PPR allows only certain components on a page to be rerendered without the need to refresh the entire page. For example, a command link or button can cause another component on the page to be rerendered, without the whole page refreshing. You can configure components to use PPR by setting one component as a target for another component's event, for example a value change or action event. For more information about partial page rendering, see the "Rerendering Partial Page Content" chapter of the Oracle Fusion Middleware Web User Interface Developer's Guide for Oracle Application Development Framework.
When you create a form, setting up PPR to work for all the components in the form can be time consuming and error prone. To alleviate this, you can set the changeEventPolicy
attribute to ppr
on value bindings. Doing so means that anytime the associated component's value changes as a result of backend business logic, the component will be automatically rerendered. You can also set an iterator binding's changeEventPolicy
to ppr
. When you do this, any action or value binding associated with the iterator will act as though its changeEventPolicy
is set to PPR
. This allows entire forms to use PPR without your having to configure each component separately.
When you drop a form and elect to include navigation controls, JDeveloper automatically sets the changeEventPolicy
attribute on the associated iterator to ppr
. JDeveloper also sets each of the navigation buttons' partialSubmit
attribute to true
. This is how command components notify the framework that PPR should occur. When you set the navigation command components' partialSubmit
attribute to true
and you set the iterator's changeEventPolicy
to ppr
, each time a navigation button is clicked, all the components in the form that use the iterator binding are rerendered. Example 22-9 shows the page definition code for the iterator created when dropping the CustomerInfoVO
collection from the Data Controls Panel as a form with navigation.
An action event occurs when a command component is activated. For example, when a user clicks a Submit button, the form is submitted, and subsequently, an action event is fired. Action events might affect only the user interface (for example, a link to change the locale, causing different field prompts to display), or they might involve some logic processing in the back end (for example, a button to navigate to the next record).
An action listener is a class that wants to be notified when a command component fires an action event. An action listener contains an action listener method that processes the action event object passed to it by the command component.
In the case of the navigation operations, when a user clicks, for example, the Next button, an action event is fired. This event object stores currency information about the current data object, taken from the iterator. Because the component's actionListener
attribute is bound to the execute
method of the Next
action binding, the Next
operation is invoked when the event fires. This method takes the currency information passed in the event object to determine what the next data object should be.
In addition, when a user clicks a navigation button, only those components associated with the same iterator as the button's action binding are processed through the lifecycle. This is because a navigation command button's partialSubmit
attribute is set to true
, and the associated iterator is configured to use PPR.
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.
You can create a form that allows a user to edit the current data, and then commit those changes to the data source. To do this, you use operations that can modify data records associated with the collection or the data control itself to create command buttons. For example, you can use the Delete
operation to create a button that allows a user to delete a record from the current range. Or you can use the built-in Submit button to submit changes.
Tip:
While you can use theCreate
operation on a form to create a new object, using the ADF Creation Form instead provides additional built-in functionality. See Section 22.6, "Creating an Input Form" for more information.
If instead of using one of the ADF built-in operations, you want to use a custom method to operate on the data in a form, see Section 28.2, "Creating Command Components to Execute Methods."
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 18.3, "Managing Transactions."
To use the operations on a form, you follow the same procedures as with the navigation operations.
To create an edit form:
From the Data Controls panel, drag the collection for which you wish to create the form, and select ADF Form from the context menu.
This creates a form using inputText
components, which will allow the user to edit the data in the fields.
In the Edit Form Fields dialog, select Include Submit Button and click OK.
You can either create new buttons for the operations you want to include, or you can rebind the Submit button so that it invokes another operation. To keep the Submit button as is and create new buttons for the operations, continue with this step. To rebind the Submit button, see Step 5.
From the Data Controls panel, select the operation associated with the collection of objects on which you wish the operation to execute, and drag it onto the JSF page. If you simply want to be able to edit the data, then the Submit button is all that is required.
For example, if you want to be able to delete a customer record, you would drag the Delete
operation associated with the CustomerInfoVO1
collection. Figure 22-6 shows the operations associated with a collection.
From the ensuing context menu, choose either ADF Button or ADF Link.
To rebind the Submit button, right-click the button in the Structure window, and choose Bind to ADF Control. In the Bind to ADF Control dialog, select the operation to which you want the button bound. Ensure that the operation you select is associated with the collection on which the form is based.
For example, if you want to be able to delete a customer record, you would select the Delete
operation associated with the CustomerInfoVO1
collection. Figure 22-6 shows the operations associated with a collection.
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 22-7 shows the commit and rollback operations for the StoreServiceAMDataControl
data control (note that for viewing simplicity, the figure omits details in the tree that appear for each view object).
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 18.3, "Managing Transactions."
Dropping any data control operation as a command button causes the same events as does dropping navigation operations. For more information, see Section 22.4.2, "What Happens When You Create Command Buttons."
The only difference is that the action bindings for the Commit
and Rollback
operations do not require a reference to the iterator, because they execute a method on the application module (the data control itself), as opposed to the iterator. Note that the Rollback
action has the RequiresUpdateModel
property set to false
. This is because the model should not be updated before the operation is executed, since all changes need to be discarded. Example 22-10 shows the action bindings generated in the page definition file for these operations.
Example 22-10 Action Bindings for Commit and Rollback Operations
<action id="Commit" RequiresUpdateModel="true" Action="commitTransaction" DataControl="StoreServiceAMDataControl"/> <action id="Rollback" RequiresUpdateModel="false" Action="rollbackTransaction" DataControl="StoreServiceAMDataControl"/>
Table 22-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 22.4.4, "What Happens at Runtime: How Action Events and Action Listeners Work."
Table 22-2 More Built-in Operations
Operation | When invoked, the associated iterator binding will... |
---|---|
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 |
|
Creates a row directly before the current row, then moves the current row pointer to the new row. Note that the range does not move, meaning that the last row in the range may now be excluded from the range. Also note that the record will not be inserted into the row set, preventing a blank row should the user navigate away without actually creating data. The new row will be created when the user submits the data. For more information, see Section 23.4.5, "What You May Need to Know About Create and CreateInsert." |
|
Same as the |
|
Same as the |
|
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 |
|
Uses the row key as a |
|
Sets the row key as a |
|
Sets the current object on the iterator, given a key's value. For more information, see Section 23.2.3, "What You May Need to Know About Setting the Current Row in a Table." |
|
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 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 more information about how the page definition works with bind variables and the |
|
Causes all items currently in the cache to be committed to the database. |
|
Clears the cache and returns the transaction and iterator to the initial state. Resets the |
|
These operations are used only in search forms. See Chapter 27, "Creating ADF Databound Search Forms" for more information. |
You can create a form that allows a user to enter information for a new record and then commit that record to the data source. You need to use a task flow that contains a method activity that will call the CreateInsert
operation before the page with the input form is displayed. This method activity causes a blank row to be inserted into the row set which the user can then populate using a form.
For example, in the StoreFront module, the customer-registration-task-flow
task flow contains the createAddress
method activity, which calls the CreateInsert
operation on the CustomerAddress
view object. Control is then passed to the addressDetails
view activity, which displays a form where the user can enter a new address, as shown in Figure 22-8.
Note:
If your application does not use task flows, then the calling page should invoke thecreateInsert
operation similar to the way in which a task flow's method activity would. For example, you could provide application logic within an event handler associated with a command button on the calling page. For more information about invoking logic with a command button, see Section 28.2, "Creating Command Components to Execute Methods."Before you create the input form, you need to create a bounded task flow that will contain both the form and the method activity that will execute the CreateInsert
operation.
To create an input form:
To the bounded task flow, add a method activity. Have this activity execute the CreateInsert
operation associated with the collection for which you are creating the form. For procedures on using method activities, see Section 15.5, "Using Method Call Activities."
In the Property Inspector, enter a string for the fixed-outcome property. For example, the createAddress
method activity in the customer-registration-task-flow
task flow has editAddress
as the fixed-outcome
value.
Add a view activity that represents the page for the input form. For information on adding view activities, see Section 15.2, "Using View Activities."
Add a control flow case from the method activity to the view activity. In the Property Inspector, enter the value of the fixed-outcome property of the method activity set in Step 2 as the value of the from-outcome
of the control flow case.
Open the page for the view activity in the design editor, and from the Data Controls panel, drag the collection for which the form will be used to create a new record, and choose ADF Form from the context menu.
Tip:
If you want the user to be able to create multiple entries before committing to the database, do the following: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
.
Drag and drop a command component from the Component Palette onto the page, and set the action
attribute to the from-outcome
just created. This will cause the task flow to return to the method activity and reinvoke the CreateInsert
operation.
Because you need to commit the new data, the application needs to execute the commit
operation of the data control. To do this, you can add a button that navigates to a return activity that calls the commit
operation. For procedures for using a return activity, see Section 15.7, "Using Task Flow Return Activities."
Best Practice:
Use the return activity unless the task flow contains data managed by more than one data control, or you need to commit the data before the end of the flow. In those cases, you can add a button to the page bound to the commit button.If you need to add a commit button to the page, do the following:
In the Data Controls panel, drag the commit operation associated with the data control that contains the collection associated with the input form, and drop it as a command button.
In the Structure window, select the command button for the commit operation.
In the Property Inspector, set the action to the outcome String that will navigate back to the method activity. You then need to add a control flow case from the page back to the activity, using the same outcome value.
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.
When you use an ADF Form to create an input form, JDeveloper:
Creates an iterator binding for the collection and an action binding for the CreateInsert
operation in the page definition for the method activity. The CreateInsert
operation is responsible for creating a row in the row set and populating the data source with the entered data. In the page definition for the page, JDeveloper creates an iterator binding for the collection and attribute bindings for each of the attributes of the object in the collection, as for any other form. If you created command buttons or links using the Commit
and Rollback
operations, JDeveloper also creates an action bindings for those operations.
Inserts code in the JSF page for the form using ADF Faces inputText
components, and in the case of the operations, commandButton
components.
For example, the StoreFront module contains a page that displays all the addresses for a customer in a table. The table includes an Add button that navigates to a form where you can input data for a new address. Once the address is created, you return to the page with the table and the new address is displayed. Figure 22-9 shows the customer-registration-task-flow
task flow with the createAddress
method activity.
Example 22-11 shows the page definition file for the method activity.
Example 22-11 Page Definition Code for a Creation Method Activity
<executables> <iterator id="CustomerAddressIterator" RangeSize="25" Binds="CustomerAddress" DataControl="StoreServiceAMDataControl"/> </executables> <bindings> <action id="CreateInsert" IterBinding="CustomerAddressIterator" InstanceName="StoreServiceAMDataControl.CustomerAddress" DataControl="StoreServiceAMDataControl" RequiresUpdateModel="true" Action="createInsertRow"/> </bindings>
When the createMethodCall
activity is accessed, the CreateInsert
action binding is invoked, which executes the CreateInsertRow
operation, and a new blank instance for the collection is created. Note that during routing from the method activity to the view activity, the method activity's binding container skips validation for required attributes, allowing the blank instance to be displayed in the form on the page.
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.
ADF Faces offers a library of dynamic components that includes dynamic form and dynamic table widgets that you can drop from the Data Controls panel. Dynamic components differ from standard components in that all the binding metadata is created at runtime. This dynamic building of the bindings allows you set display information using control hints on a view object instead of configuring the information in the Edit Form Fields dialog as you drop the control onto the page. Then if you want to change how the data displays, you need only change it on the view object, and all dynamic components bound to that view object will change their display accordingly. With standard components, if you want to change any display attributes (such as the order or grouping of the attributes) you would need to change each page on which the data is displayed.
For example, in the StoreFront module, you could set the Category and Field Order attribute hints on the CustomerInfoVO
view object that groups the FirstName
and LastName
attributes together and at the top of a form (or at the leftmost columns of a table), the ConfirmedEmail
and MobilePhoneNumber
together and at the bottom of a form (or the rightmost columns of a table), and the MembershipID
and MembershipType
together and at the middle of a form or table. You could make it so that the PersonId
does not display at all. For more information about control hints on view objects, see Section 5.13, "Defining Attribute Control Hints for View Objects."
Figure 22-10 shows a dynamic form at runtime created by dragging and dropping the CustomerInfoVO
view object with control hints set as described previously, as a dynamic form. Note that the input fields are grayed out because the view object is nonupdateable.
To use dynamic forms you first need to set control hints (especially the order and grouping hints) on any corresponding view objects. Next you import the libraries for the dynamic components. You can then drop the dynamic form or table widgets onto your page.
To use dynamic components:
Set UI hints on the corresponding view objects. For the Category hint, enter a string that can be used to group attributes together. For example, in the CustomerInfoVO
hints, the FirstName
and LastName
attributes both have name
as the value for the Category UI hint. The Field Order hint determines the order the attributes are displayed within a category. For example, in the CustomerInfoVO
hints, the FirstName
attribute has a Field Order value of 1
and the LastName
attribute has a Field Order value of 2
.
For procedures on creating UI hints, see Section 5.13, "Defining Attribute Control Hints for View Objects."
If not already included, import the dynamic component library.
In the Application Navigator, right-click the view project in which the dynamic components will be used, and from the context menu, choose Project Properties.
In the tree, select JSP Tag Libraries.
On the JSP Tag Libraries page, click Add.
In the Choose Tag Libraries dialog, select ADF Dynamic Components, and click OK.
On the JSP Tag Libraries page, click OK.
From the Data Controls panel, select the collection that represents the view object.
Drag the collection onto the page, and from the context menu, choose Forms > ADF Dynamic Form.
Tip:
If dynamic components are not listed, then the library was not imported into the project. Repeat Step 2.In the Property Inspector, enter the following: for the Category field, .
Category: Enter the string used as the value for the Category UI hint for the first group you'd like to display in your form. For example, in Figure 22-10, the Category value would be name
.
Editable: Enter true
if you want the data to be editable (the default). Enter false
if the data should be read-only.
Repeat Steps 7 and 8 for each group that you want to display on the form. For example, the form in Figure 22-10 is actually made up of three different forms: one for the category name
, one for the category membership
, and one for the category contact
.
When you drop a dynamic form, only a binding to the iterator is created. Example 22-12 shows the page definition for a page that contains one dynamic form component created by dropping the CustomerInfoVO
collection. Note that no attribute bindings are created.
Example 22-12 Page Definition Code for a Dynamic Form
<pageDefinition xmlns="http://xmlns.oracle.com/adfm/uimodel" version="11.1.1.53.2" id="DynamicFormPageDef" Package="package.pageDefs"> <parameters/> <executables> <iterator Binds="CustomerInfoVO1" RangeSize="25" DataControl="StoreServiceAMDataControl" id="CustomerInfoVO1Iterator"/> </executables> <bindings/> </pageDefinition>
JDeveloper inserts a a form
tag which contains a dynamic form tag for each of the forms dropped. The form tag's value is bound to the iterator binding, as shown in Example 22-13. This binding means the entire form is bound to the data returned by the iterator. You cannot set display properties for each attribute individuality, nor can you rearrange attributes directly on the JSF page.
Example 22-13 JSF Page Code for a Dynamic Form
<af:document> <af:messages/> <af:form> <dynamic:form value="#{bindings.CustomerInfoVO1Iterator}" category="name"/> <dynamic:form value="#{bindings.CustomerInfoVO1Iterator}" category="member"/> <dynamic:form value="#{bindings.CustomerInfoVO1Iterator}" category="contact"/> </af:form> </af:document>
Tip:
You can set certain properties that affect the functionality of the form. For example, you can make a form available for upload, set the rendered property, or set a partial trigger. To do this, select theaf:form
tag in the Structure window, and set the needed properties using the Property Inspector.When a page with dynamic components is rendered, the bindings are created just as they are when items are dropped from the Data Controls panel at design time, except that they are created at runtime. For more information, see Section 22.3.2, "What Happens When You Create a Form."
Tip:
While there is a slight performance hit because the bindings need to be created at runtime, there is also a performance gain because the JSF pages do not need to be regenerated and recompiled when the structure of the view object changes.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.You can modify certain aspects of the default components dropped from the Data Controls panel. You can use the Structure window to change the order in which components are displayed, to add new components or change existing components, or to delete components. You can use the Property Inspector to change or delete bindings, or to change the label displayed for a component.
To modify default components and bindings:
Use the Structure window to do the following:
Change the order of the UI components by dragging them up or down the tree. A black line with an arrowhead denotes where the UI component will be placed.
Add a UI component. Right-click an existing UI component in the Structure window and choose to place the new component before, after, or inside the selected component. You then choose from a list of UI components.
Bind a UI component. Right-click an existing UI component in the Structure window and choose Bind to ADF Control. You can then select the object to which you want your component bound.
Rebind a UI component. Right-click an existing UI component in the Structure window and choose Rebind to another ADF Control. You can then select the new control object to which you want your component bound.
Delete a UI component. Right-click the component and choose Delete. If you wish to keep the component, but delete the binding, you need to use the Property Inspector. See the second bullet point in Step 2.
With the UI component selected in the Structure window, you can then do the following in the Property Inspector:
Add a non-ADF binding for the UI component. Enter an EL expression in the Value field, or use the dropdown menu and choose Edit.
Delete a binding for the UI component by deleting the EL expression.
Change the label for the UI component. By default, the label is bound to the binding's label
property of its hint. This property allows your page to use the UI control hints for labels that you have defined for your entity object attributes or view object attributes. The UI hints allow you to change the value once and have it appear the same on all pages that display the label.
You can change the label just for the current page. To do so, select the label
attribute. You can enter text or an EL expression to bind the label value to something else, for example, a key in a properties or resource file.
For example, the inputText
component used to display the name of a product might have the following for its Label
attribute:
#{bindings.ProductName.hints.label}
However, you could change the expression to instead bind to a key in a properties file, for example:
#{properties['productName']}
In this example, properties
is a variable defined in the JSF page used to load a properties file.
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.