Reference : Initiate Control Flow Within A Region From Its Parent Page Functional Pattern

This topic contains the following sections:

Problem Description

There are often cases when an application page requires some type of interaction with one of its regions. If the interaction depends on application data being shared between the two, typically either input parameters or a <data-control-scope> of “shared” is utilized by the region. If only a small payload of application data should be shared without restarting the region, contextual framework events can be used. But, when an application page must initiate control flow within one of its regions the best approach is to utilize the queueActionEventInRegion(…) method located within the oracle.adf.view.rich.component.rich.fragment.RichRegion class. API documentation is available at  http://download.oracle.com/docs/cd/E14571_01/apirefs.1111/e10684/toc.htm

Technical Pattern Description

The following document describes the recommended development approach to initiate control flow within a region from its parent page. Although other development approaches may be possible to achieve the same desired use case behavior, the recommended approach described within this document is considered the most comprehensive and least complex.

The User Experience

The commonly desired application development use case behavior for initiating control flow within a region from its parent page is as follows:

  1. During application runtime, the user selects a button or performs an action on the parent page.

  2. The region performs control flow to display the appropriate page fragment.

  3. Buttons on parent page adjust based on the current page fragment displayed within the region.

For example, in the sample application the parent page provides the “Employees” and “Departments” buttons to alternate between display of the Employees and Departments page fragments within its region. It also provides “Locations” and “Location Detail” buttons to alternate between the display of the Locations and Location Detail page fragments within a nested region on the Departments page fragment. When the “Employees” button is selected, the Employees page fragment is displayed within the region. The buttons on the parent page are modified to enable the “Departments” button, but disable the “Employees”, “Locations”, and “Location Detail” buttons.

ADF Region Navigation Using ActionEvent Application - Departments button enabled

When the “Departments” button is selected, the Departments page fragment is displayed within the region and the Locations page fragment is displayed within its nested region. The buttons on the parent page are modified to enable the “Employees”, “Locations”, and “Location Detail” buttons, but disable the “Departments” button.

ADF Region Navigation Using ActionEvent Application - Departments button disabled

When the “Location Detail” button is selected, the Location Detail page fragment is displayed within the nested region.

ADF Region Navigation Using ActionEvent Application - Location Detail button selected

The Artifacts

When incorporating the ability of a parent page to initiate control flow within one of its regions, the following development constructs are recommend to implement the desired use case behavior:

  • queueActionEventInRegion()– used to queue an ActionEvent on a region or nested region to initiate control flow. Calling this method on a RichRegion mimics the behavior of a UIXCommand inside the region queuing the ActionEvent

  • Region Capabilities – used by a parent page to identify the current capabilities (outcomes) of one of its regions based on the region’s current state. Region Capabilities require the availability of a specified region’s regionModel through an EL Expression. An EL expression should never access bindings in any other binding container than the current binding container (e.g.: #{bindings.taskflowdefinition1}). Therefore in cases where a regionModel cannot be reached within the current binding container (e.g.: nested regions), Region Capabilities cannot be used. A nested region’s nested binding container might not exist yet or might have already been released.

  • Partial Triggers used by buttons on the parent page to force them to re-render when the dynamic region changes. Otherwise, the button’s disabled state can be unpredictable.

Implementing the Pattern

In this example, a home page provides commandButtons to alternate between the display of its region’s “Employees” and “Departments” page fragments. It also provides a second set of commandButtons to alternate between the display of its nested region’s “Locations” and “Location Detail” page fragments.

ADF Region Navigation Using ActionEvent Application - Employees page fragment

The region’s task flow definition includes “Employees” and “Departments” view activities along with the control flow between them.

Region task flow definition includes Employees and Departments view activities

The nested region’s task flow definition includes “Locations” and “LocationDetail” view activities along with the control flow between them.

Nested region task flow definition includes Locations and LocationDetail view activities

The commandButtons on the home page are assigned actionListener methods to initiate navigation within the region and nested region. Managed beans referenced by the actionListeners should utilize a request memory scope. Region capabilities identify when the commandButtons should be enabled/disabled based on the available outcomes defined by the current state of the region’s regionModel. Since a nested region’s regionModel is not available to the parent page binding container, Region Capabilities reference the region, not the nested region. Partial Triggers have been added to re-render the buttons when the dynamic region changes. Otherwise, the button’s disabled state can be unpredictable.

<af:commandButton text="Employees"
     actionListener="#{ADFRegionNavigationBean.handleOuterPageActionEmployees}"
    inlineStyle="margin:10px;"
    partialTriggers="taskf1"
    disabled="#{!bindings.taskflowdefinition1.regionModel.capabilities['employees']}"/>

<af:commandButton text="Departments"
     actionListener="#{ADFRegionNavigationBean.handleOuterPageActionDepartments}"
    inlineStyle="margin:10px;"
    partialTriggers="taskf1"
    disabled="#{!bindings.taskflowdefinition1.regionModel.capabilities['departments']}"/>

<af:commandButton text="Locations"
     actionListener="#{ADFRegionNavigationBean.handleOuterPageActionLocations}"
    inlineStyle="margin:10px;"
    partialTriggers="taskf1"
    disabled="#{!bindings.taskflowdefinition1.regionModel.capabilities['employees']}"/>

<af:commandButton text="Location Detail"
     actionListener="#{ADFRegionNavigationBean.handleOuterPageActionLocationDetail}"
    inlineStyle="margin:10px;"
    partialTriggers="taskf1"
    disabled="#{!bindings.taskflowdefinition1.regionModel.capabilities['employees']}"/>

The methods assigned to the commandButton actionListeners should be similar to the following methods. The end result of these methods is the queuing of an ActionEvent to perform region navigation based on the specified outcome.

private String region = "taskf1";
private String outcome = "departments";

public void handleOuterPageActionDepartments(ActionEvent actionEvent) {

    outcome = "departments";
    handleOuterPageAction(actionEvent);
}

public void handleOuterPageActionEmployees(ActionEvent actionEvent) {
    region = "taskf1";
    outcome = "employees";
    handleOuterPageAction(actionEvent);
}

public void handleOuterPageActionLocationDetail(ActionEvent actionEvent) {
    region = "taskf1:neste1";
    outcome = "location-detail";
    handleOuterPageAction(actionEvent);
}

public void handleOuterPageActionLocations(ActionEvent actionEvent) {
    region = "taskf1:neste1";
    outcome = "locations";
    handleOuterPageAction(actionEvent);
}

public void handleOuterPageAction(ActionEvent actionEvent) {
    UIComponent regionComponent = actionEvent.getComponent().findComponent(region);
    if (regionComponent instanceof RichRegion) {
       FacesContext fc = FacesContext.getCurrentInstance();
       ExpressionFactory ef = fc.getApplication().getExpressionFactory();
       ELContext elc = fc.getELContext();
       MethodExpression me = ef.createMethodExpression(elc,
         "#{ADFRegionNavigationBean.getOutcomeExpression}", String.class, new
         Class[] { });
        ((RichRegion)regionComponent).queueActionEventInRegion(me,
         null, null, false, -1, -1, PhaseId.ANY_PHASE);

    }
}

public String getOutcomeExpression() {
    return outcome;
}

The queueActionEventInRegion(…) method queues an ActionEvent so it behaves as if you queued it on a UIXCommand component existing inside the region or nested region. When passing the String identifying the region or nested region component to the findComponent() method the following syntax can be used:

  • “R1:R2:R3…” – looks for R3 relative to the commandButton initiating the ActionEvent. This syntax wouldn’t work if the button were located inside R1.

  • “:R1:R2:R3…” – always looks for R3 starting from the root of the component tree. Therefore, this syntax should always work.

For further information on queueActionEventInRegion(…) method signature and parameters, refer to Javadoc within the oracle.adf.view.rich.component.rich.fragment.RichRegion class. API documentation is available at  http://download.oracle.com/docs/cd/E14571_01/apirefs.1111/e10684/toc.htm

Interaction Behavior

  1. Button on parent page is selected and invokes a method.

  2. Method retrieves the specified region UI component from the passed ActionEvent.

  3. Method identifies the appropriate outcome to perform within the region.

  4. Method queues the ActionEvent on region UI component using queueActionEventInRegion().

  5. ActionEvent is executed on the region UI component.

  6. Region performs control flow <from-outcome>.

  7. Region capabilities determine the available outcomes based on the region’s current state.

Parent page buttons are enabled or disabled based on the results of the region capabilities.

Appendix - Object Definitions Used by the Prototype

In order to test this pattern out, included is a JDeveloper 11g Application called RegionNavigationUsingActionEvent.zip that can be unzipped into your designated work area and explored / executed from within JDeveloper 11g. Simply download ADFRegionNavigationUsingActionEventApplication.zip at http://www.oracle.com/technetwork/developer-tools/adf/adfregionnavigationusingactionevent-129081.zip, unzip the archive, open the ADFRegionNavigationUsingActionEventApplication.jws within JDeveloper 11g and explore. This sample using an Oracle Database version 10g or higher and utilizes the EMPLOYEES and DEPARTMENTS database tables.

Note: This sample uses the HR schema that comes with the Oracle Database since version 9i. In some cases, you will need to unlock the HR account in the database.


Copyright © 1997, 2010, Oracle