Oracle® Application Development Framework Developer's Guide 10g (10.1.3.1.0) Part Number B28967-01 |
|
|
View PDF |
In addition to tables and forms, you can also display master-detail data in hierarchical trees. The ADF Faces tree
component, available from the Data Control Palette, can display multiple root nodes that are populated by a binding on a master object. Each root node in the tree may have any number of branches, which are populated by bindings on detail objects. A tree can have multiple levels of nodes, each representing a detail object of the parent node. Each node in the tree is indented to show its level in the hierarchy.
The tree
component includes mechanisms for expanding and collapsing the tree nodes; however, it does not have focusing capability. If you need to use focusing, consider using the ADF Faces TreeTable
component (for more information, see Section 8.5, "Using Tree Tables to Display Master-Detail Objects"). By default, the icon for each node in the tree is a folder; however, you can use your own icons for each level of nodes in the hierarchy.
Figure 8-3 shows an example of a tree from the SRManage page of the SRDemo application. The tree displays two levels of nodes: staff members and service requests assigned to them. The root nodes display staff members. The branch nodes display open or pending service requests assigned to each staff member.
A tree consists of a hierarchy of nodes, where each subnode is a branch off a higher level node. Each node level in a databound ADF Faces tree
is populated by a different data collection. In JDeveloper, you define a databound tree using the Tree Binding Editor, which enables you to define the rules for populating each node level in the tree. There must be one rule for each node level in the hierarchy. Each rule defines the following node level properties:
The data collection that populates that node level
The attributes from the data collection that are displayed at that node level
An accessor method that returns a detail object to be displayed as a branch of the current node level
To display master-detail objects in a tree:
Drag the master object from the Data Control Palette, and drop it onto the page. This should be the master data that will represent the root level of the tree.
Note: The root node must be a collection represented by a method return or accessor return. You cannot use a single-object accessor return as the root node of a tree. |
In the context menu, choose Trees > ADF Tree.
JDeveloper displays the Tree Binding Editor, as shown in Figure 8-4.
In the Edit Rule page of the Tree Binding Editor, define a rule for each node level that you want to appear in the tree. To define a rule you must select the following items:
Data Collection Definition: Select the data collection that will populate the node level you are defining.
The first rule defines the root node level. So, for the first rule, select the same collection that you dragged from the Data Control Palette to create the tree, which was a master collection.
To create a branch node, select the appropriate detail collection. For example, to create a root node of users, you would select the User
collection for the first (root node) rule; to create a branch that displays services requests, you would select the ServiceRequest
collection in the branch rule.
Display Attribute: Select one or more attributes to display at each node level. For example, for a node of users, you might select both the FirstName and LastName attributes.
Branch Rule Accessor: Select the accessor method that returns the detail collection that you want to appear as a branch under the node level you are defining. The list displays only the accessor methods that return the detail collections for the master collection you selected for the rule. If you choose <none>, the node will not expand to display any detail collections, thus ending the branch. For example, if you are defining the User
node level and you want to add a branch to the service requests for each user, you would select the accessor method that returns the service request collection. Then, you must define a new rule for the serviceRequest
node level.
Polymorphic Restriction: Optionally, you can define a node-populating rule for an attribute whose value you want to make a discriminator. The rule will be polymorphic because you can define as many node-populating rules as desired for the same attribute, as long as each rule specifies a unique discriminator value. The tree will display a separate branch for each polymorphic rule, with the node equal to the discriminator value of the attribute.
Tip: Be sure to click Add New Rule after you define each rule. If you click OK instead, the last rule you defined will not be saved. When you click Add New Rule, JDeveloper displays the Show Rules tab of the Tree Binding Editor, where you can verify the rules you have created. |
Use the Show Rules page of the Tree Binding Editor, shown in Figure 8-5, to:
Change the order of the rules
The order of the rules should reflect the hierarchy that you want the tree to display.
Identify the icons you want displayed at each node level
By default, every node level displays a folder icon. You can use different icons for each node level (represented by a rule) and different icons for the different states of the node: open, closed, end of a branch.
Delete rules
The first rule listed in the Show Rules page of the Tree Binding Editor, populates the root node level of the tree. So, be sure that the first rule populates the logical root node for the tree, depending on the structure of your data model.
For example, in the sample tree previously shown in Figure 8-3, the first rule would be the one that populates the user nodes. The order of the remaining rules should follow the hierarchy of the nodes you want to display in the tree.
When you drag and drop from the Data Control Palette, JDeveloper does many things for you. For a full description of what happens and what is created when you use the Data Control Palette, see Section 5.2.3, "What Happens When You Use the Data Control Palette".
When you create a databound tree using the Data Control Palette, JDeveloper adds binding objects to the page definition file, and it also adds the tree tag to the JSF Page. The resulting UI component is fully functional and does not require any further modification.
Example 8-2 shows the code generated in a JSF page when you use the Data Control Palette to create a tree. This sample tree displays two levels of nodes: users and service requests. The User
collection is the root node and is returned by the findAllStaff
method.
Example 8-2 Code Generated in the JSF Page for a Databound Tree
<h:form> <af:tree value="#{bindings.findAllStaff1.treeModel}" var="node"> <f:facet name="nodeStamp"> <af:outputText value="#{node}"/> </f:facet> </af:tree> </h:form>
By default, the af:tree
tag is created inside a form. The value
attribute of the tree tag contains an EL expression that binds the tree component to the findAllStaff1
tree binding object in the page definition file. The treeModel
property refers to an ADF class that defines how the tree hierarchy is displayed, based on the underlying data model. The var
attribute provides access to the current node.
In the f:facet
tag, the nodeStamp
facet is used to display the data for each node. Instead of having a component for each node, the tree repeatedly renders the nodeStamp
facet, similar to the way rows are rendered for the ADF Faces table component.
The ADF Faces tree component uses an instance of the oracle.adf.view.faces.model.PathSet
class to display expanded nodes. This instance is stored as the treeState
attribute on the component. You may use this instance to programmatically control the expanded or collapsed state of an element in the hierarchy. Any element contained by the PathSet
instance is deemed expanded. All other elements are collapsed.
Example 8-3 shows the binding objects defined in the page definition file for the ADF databound tree.
Example 8-3 Binding Objects Defined the Page Definition File for a Databound Tree
<executables> <methodIterator id="findAllStaffIter" Binds="findAllStaff.result" DataControl="SRPublicFacade" RangeSize="10" BeanClass="oracle.srdemo.model.entities.User"/> </executables> <bindings> <methodAction id="findAllStaff" InstanceName="SRPublicFacade.dataProvider" DataControl="SRPublicFacade" MethodName="findAllStaff" RequiresUpdateModel="true" Action="999" ReturnName="SRPublicFacade.methodResults. SRPublicFacade_dataProvider_findAllStaff_result"/> <tree id="findAllStaff1" IterBinding="findAllStaffIter"> <AttrNames> <Item Value="city"/> <Item Value="countryId"/> <Item Value="email"/> <Item Value="firstName"/> <Item Value="lastName"/> <Item Value="postalCode"/> <Item Value="stateProvince"/> <Item Value="streetAddress"/> <Item Value="userId"/> <Item Value="userRole"/> </AttrNames> <nodeDefinition DefName="oracle.srdemo.model.entities.User" id="UserNode"> <AttrNames> <Item Value="firstName"/> <Item Value="lastName"/> </AttrNames> <Accessors> <Item Value="assignedToCollection"/> </Accessors> </nodeDefinition> <nodeDefinition DefName="oracle.srdemo.model.entities.ServiceRequest" id="ServiceRequestNode"> <AttrNames> <Item Value="problemDescription"/> </AttrNames> </nodeDefinition> </tree> </bindings>
The page definition file contains the rule information defined in the Tree Binding Editor. In the executables
element, notice that although the tree displays two levels of nodes, only one iterator binding object is needed. This iterator iterates over the master collection, which populates the root nodes of the tree. The accessor you specified in the node rules return the detail data for each branch node.
In the example, the iterator happens to be a method iterator because a method return was dragged from the Data Control Palette and dropped on the page as an ADF tree. If an accessor return had been dragged from the Data Control Palette, this would be an accessor iterator instead of a method iterator. Because a method iterator is used in this example, a corresponding methodAction
is defined in the bindings
element. The methodAction
encapsulates the details about how to invoke the method, which returns the data collection.
The tree
element is the value binding for all the attributes displayed in the tree. The iterBinding
attribute of the tree
element references the iterator binding that populates the data in the tree. The AttrNames
element within the tree
element defines binding objects for all the attributes in the master collection. However, the attributes that you select to appear in the tree are defined in the AttrNames
elements within the nodeDefinition
elements.
The nodeDefinition
elements define the rules for populating the nodes of the tree. There is one nodeDefinition
element for each node, and each one contains the following attributes and subelements:
DefName
: An attribute that contains the fully qualified name of the data collection that will be used to populate the node.
id
: An attribute that defines the name of the node.
AttrNames
: A subelement that defines the attributes that will be displayed in the node at runtime.
Accessors
: A subelement that defines the accessor method that returns the next branch of the tree.
The order of the nodeDefintion
elements within the page definition file defines the order or level of the nodes in the tree, were the first nodeDefinition
element defines the root node. Each subsequent nodeDefinition
element defines a sub-node of the one before it.
For more information about the elements and attributes of the page definition file, see Section A.7, "<pageName>PageDef.xml".
Tree components use oracle.adf.view.faces.model.TreeModel
to access data. This class extends CollectionModel
, which is used by the ADF Faces table
component to access data. For more information about the TreeModel
class, refer to the ADF Faces Javadoc.
When a page with a tree is displayed, the iterator binding on the tree populates the root nodes. When a user collapses or expands a node to display or hide its branches, a DisclosureEvent
event is sent. The isExpanded
method on this event determines whether the user is expanding or collapsing the node. The DisclosureEvent
event has an associated listener.
The DisclosureListener
attribute on the tree is bound to the accessor method specified in the node rule defined in the page definition file. This accessor method is invoked in response to the DisclosureEvent
event; in other words, whenever a user expands the node the accessor method populates the branch nodes.