Showing posts with label Region Interaction. Show all posts
Showing posts with label Region Interaction. Show all posts

Saturday, November 6, 2010

ADF UI - Region Interaction: From parent page to child region task flow

If you drop a task flow as a region in a jsf page and if you want to refresh the task flow region based on some action in the jsf, please go through this post.

Sample UseCase:
For example if a Jsf Page contains departments table and on selecting a department from the table and click on button 'Show Employees', it should display the employees in the selected department. But suppose the employee details should come from a different task flow. We need to establish the communication between the parent jsf page and the task flow region in it. Sample application for this example can be downloaded from here.

Implementation Steps:

Task flow refresh Principle:
If you drop a task flow that takes some parameters as a region in a jsff page, the task flow binding will be added in the pagedef file. If you set refresh='ifNeeded' for the task flow binding, the task flow will be re-executed each time when the value for one of the passed parameters got changed. To be clear, here re-execution means the task-flow will re-execute from it's default activity in the task flow diagram.

This example depends on the above principle.

1. Create a jsff page and include departments table and add a button 'Show Employees'.
2. Create a task flow that takes deptId as parameter and fetches the employees present the given department and shows them in a table.

Task flow diagram with input parameter deptId:

3. Specify actionListener for the 'Show Employees' button and in the actionListener method, get the deptId selected in departments table and set to to a pageFlowScope variable.

Java bean containing the actionListener method for 'Show Employees' button:
public class ExampleBean { private Integer deptId; public void buttonClicked(ActionEvent ae){ Row currentDeptRow=(Row)ADFUtil.evaluateEL("#{bindings.DeptVO.currentRow}"); ADFUtil.setEL("#{pageFlowScope.deptId}",currentDeptRow.getAttribute("Deptno")); } public void setDeptId(Integer deptId) { this.deptId = deptId; } public Integer getDeptId() { return deptId; } }


4. Drop the employee details task flow as a region in the jsf page. Pass the same above pageFlowScope variable as a parameter to the dropped taskflow. Specify refresh="ifNeeded" for the task flow binding in pagedef.

Task flow binding in the pagedef:

   <taskFlow id="TaskFlow21"               taskFlowId="/com/demo/taskflows/TaskFlow2.xml#TaskFlow2"               xmlns="http://xmlns.oracle.com/adf/controller/binding"               Refresh="ifNeeded" activation="deferred">       <parameters>         <parameter id="deptId" value="#{pageFlowScope.deptId}"/>       </parameters>     </taskFlow>


That's it. This is how it works: When the user selects department in jsff and clicks on 'Show Employees' button, the actionListener method sets the pageFlowScope variable with the deptId selected and the same will be passed to the dropped task flow. As the task flow re-executes if any of it's input parameter changes, the employees will be queried based on passed deptId and the task flow will refreshed with the corresponding employee details. No 'partialTriggers' is required in this case. Refresh of task flow will be triggered automatically when the input parameter value is changed.

Sample screen shots:

Friday, November 5, 2010

ADF UI - Region Interaction: Between two peer region task flows present in a single parent page

Generally, if we want to refresh a field or part of the page, we use ppr (partial page rendering) in ADF. We just specify the id of the component (whose state change should trigger refresh) for the partialTriggers property of the required component to be refreshed. It's that simple. But, when we use task flows as regions in our pages, many times we need to establish communication between the parent page containing the region and the region itself. Similarly if there are two regions in the same jsff and some times we need to refresh one region based on some actin done on another region. Here, in this post I'm going to explain this case.

Sample UseCase:
For example, we have two task flows- one task flow displays the departments in a table and the second task flow shows the employees present in department for which the Deptno is passed as a task flow parameter. Now, the requirement is that based on the department selected in the first region, the second region needs to be refreshed with the employees in that particular selected department provided these two regions are dropped in a single jsf page. Sample example application can be downloaded from here. Here, actually we're establishing a communication between the two regions present in the same jsf page.

Implementation Details:
Before going through the implmentation steps, lets have a quick review of task flow basics.

If you drop a task flow that takes some parameters as a region in a jsff page, the task flow binding will be added in the pagedef file. If you set refresh='ifNeeded' for the task flow binding, the task flow will be re-executed each time when the value for one of the passed parameters got changed. To be clear, here re-execution means the task-flow will re-execute from it's default activity in the task flow diagram.

In other words, if you drop task flow TF that takes parameters param1,param2 in a jsf page abc.jsff, and if you specify refresh='ifNeeded' for the task flow binding in pagdef, and if you give the values for param1 and param2 as #{pageFlowScope.param1} and #{pageFlowScope.param2}, the task flow will be re-executed if any of the pageflowScope param values changed to a different value.

Knowing the above point is very important to implement interaction between two regions.

Implementation Steps:
1. Make two task flows ready -
i. TaskFlow1 - This task flow displays departments table with a button 'Show Employees'.
ii. TaskFlow2 - This task flow takes a parameter deptId and based on the passed deptId, it'll query the employees in the dept and displays them in a table.

TaskFlow2 Diagram:

2. Create a java bean with the property deptId and generate accessors for it. Now, create data control for the bean.

Java bean containing the property 'deptId':
package com.demo.beans; public class SharedBean { private Integer deptId; public void setDeptId(Integer deptId) { this.deptId = deptId; } public Integer getDeptId() { return deptId; } }

3. Now, in the actionListener method for 'Show Employees' button in task flow1, just get the selected deptId and set to the shared bean data control property.

ActionListener method code:
public void buttonClicked(ActionEvent ae) { Row currentDeptRow = (Row)ADFUtil.evaluateEL("#{bindings.DeptVO.currentRow}"); ADFUtil.setEL("#{bindings.deptId.attributeValue}", currentDeptRow.getAttribute("Deptno")); }

4. Drop the two task flows in a single jsff page. It'll ask for the parameter for the TaskFlow2, give the same shared bean data control property 'deptId' as the parameter. Don't forget to set the 'refresh' property for the TaskFlow2 task flow binding to 'ifNeeded'.

Parent jsff page code containing these two regions:
<?xml version='1.0' encoding='windows-1252'?> <jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" version="2.1" xmlns:af="http://xmlns.oracle.com/adf/faces/rich" xmlns:f="http://java.sun.com/jsf/core"> <af:panelGroupLayout id="pgl1"> <af:showDetailHeader text="Interaction between two peer regions" disclosed="true" id="sdh1"> <af:panelGroupLayout id="pgl3" layout="scroll"> <af:region value="#{bindings.TaskFlow11.regionModel}" id="r1"/> </af:panelGroupLayout> <af:spacer width="10" height="10" id="s1"/> <af:panelGroupLayout id="pgl4" layout="scroll"> <af:region value="#{bindings.TaskFlow21.regionModel}" id="r2"/> </af:panelGroupLayout> </af:showDetailHeader> </af:panelGroupLayout> </jsp:root>

Parent Jsff pagedef file:
<?xml version="1.0" encoding="UTF-8" ?> <pageDefinition xmlns="http://xmlns.oracle.com/adfm/uimodel" version="11.1.1.56.60" id="ParentPagePageDef" Package="com.demo.fragments"> <parameters/> <executables> <variableIterator id="variables"/> <taskFlow id="TaskFlow11" taskFlowId="/com/demo/taskflows/TaskFlow1.xml#TaskFlow1" activation="deferred" xmlns="http://xmlns.oracle.com/adf/controller/binding" Refresh="ifNeeded"/> <taskFlow id="TaskFlow21" taskFlowId="/com/demo/taskflows/TaskFlow2.xml#TaskFlow2" activation="deferred" xmlns="http://xmlns.oracle.com/adf/controller/binding" Refresh="ifNeeded"> <parameters> <parameter id="deptId" value="#{bindings.deptId.attributeValue}"/> </parameters> </taskFlow> <iterator Binds="root" RangeSize="25" DataControl="SharedBean" id="SharedBeanIterator"/> </executables> <bindings> <attributeValues IterBinding="SharedBeanIterator" id="deptId"> <AttrNames> <Item Value="deptId"/> </AttrNames> </attributeValues> </bindings> </pageDefinition>

That's it. Now, when the user selects a dept in TaskFlow1 region and clicks on 'Show Employees', the second task flow will be re-executed as the actionListener method changes value of the input parameter of the TaskFlow2. This triggers re-execution of TaskFlow2 and corresponding employees in selected dept in TaskFlow1 will be displayed in TaskFlow2.

So, here we're establishing communication by using shared bean data control property. Sample Screenshots below:

Related Posts with Thumbnails