ADF Code Corner: 97. How-To Defer Train-Stop Navigation For Custom Form Validation or Other Developer Interaction
ADF Code Corner: 97. How-To Defer Train-Stop Navigation For Custom Form Validation or Other Developer Interaction
ADF Code Corner: 97. How-To Defer Train-Stop Navigation For Custom Form Validation or Other Developer Interaction
Abstract:
twitter.com/adfcodecorner
Oracle ADF Code Corner is a loose blog-style series of how-to documents that provide solutions
to real world coding problems.
Disclaimer: All samples are provided as is with no guarantee for future upgrades or error
correction. No support can be given through Oracle customer support.
Please post questions or report problems related to the samples in this series on the OTN forum
for Oracle JDeveloper: http://forums.oracle.com/forums/forum.jspa?forumID=83
Introduction
The train component and the associated train model in bounded task flows is a powerful feature
in ADF that can be tailored and customized for different kind of cases beyond simple view to view
navigation. In this article, the user train stop selection to naigate to another view is intercepted for
the developer to object and cancel or continue with the navigation.
The screenshots below are taking from the sample built for this code corner article. In this
sample, when a user clicks on a train stop icon to perform navigation …
… instead of navigating to the view associated with the train stop, a popup is displayed. The
popup, for example, could be shown if custom validation fails for a view or if data needs to be be
committed.
2
How-to defer train-stop navigation for custom form
ADF CODE CORNER validation or other developer interaction
If the user OKs the dialog, navigation is performed according to the train navigation rule. If the
user cancels the navigation, the current view is not left.
3
How-to defer train-stop navigation for custom form
ADF CODE CORNER validation or other developer interaction
Using a page template is a convenient and time saving option to add a popup dialog to views without
coding the popup into each view. In JDeveloper 11g R2, page templates can be nested, which allows you
to reference functional templates – like this containing a popup to share – with page layout templates.
Each view contains an af:train component that in its nodeStamp facet has a commanNavigationItem
component defined. Using a commanNavigationItem in the nodeStamp allows developers to change
the default train rendering and behavior. The commanNavigationItem ActionListener property is set
up to point to a managed bean method. Each view and train stop references the same managed bean
method.
The managed bean method's responsibility is
To determine the train stop the user clicked on
Show the popup dialog (or if the use case is to conditionally show the popup, to determine the
condition)
4
How-to defer train-stop navigation for custom form
ADF CODE CORNER validation or other developer interaction
The commanNavigationItem has an f:attribute component added to keep track of which train stop the
user clicked on. The f:attribute item adds a custom attribute to the ADF Faces component that can be
accessed in the managed bean. The #{trainNode} reference is of type TaskFlowTrainStopModel
and exposes the train stop navigation case by its getOutcome() method.
The commanNavigationItem instance is accessible from the managed bean method using the
ActionEvent object that is passed to it.
Two managed beans are used in this sample. The TrainHandlerBean is defined in request scope and is
referenced from the commanNavigationItem in the af:train component on the views and the af:popup
5
How-to defer train-stop navigation for custom form
ADF CODE CORNER validation or other developer interaction
component in the template. The TrainHandlerBeanHelper is configured in viewScope and holds the
reference to the outcome value of the train stop clicked by the user. The TrainHandlerBeanHelper is
configured as a managed property in the TrainHandlerBean definition. Both beans are configured in the
bounded task flow metadata.
Shown below is the managed bean configuration for the TrainHandlerBean. As you can see, the
TrainHandlerBeanHelper bean is referenced as a managed property, which is required for the popup
listener that notifies the managed bean about the dialog close by the user to get access to the user selected
train node.
The two managed bean code listings are shown below. I commented the code source so you know what
each method therein does and from where it is accessed.
TrainHandlerBean (request scope)
The TrainHandlerBean implements all of the logic. It saves the user selected train stop node's outcome
value (the implicit navigation case) in the TrainHandlerBeanHelper so the information persists beyond
the request. The bean also opens the popup dialog by searching within the ADF region container for the
af:popup instance.
When the popup is closed by the user pressing Ok or Cancel, the managed bean is called again. If the
selected outcome is Ok, then the bean queues an action event on the ADF region to navigate to the next
view.
6
How-to defer train-stop navigation for custom form
ADF CODE CORNER validation or other developer interaction
package adf.sample;
import javax.el.ELContext;
import javax.el.ExpressionFactory;
import javax.el.MethodExpression;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import javax.faces.event.PhaseId;
import oracle.adf.controller.TaskFlowTrainStopModel;
import oracle.adf.view.rich.component.rich.RichPopup;
import oracle.adf.view.rich.component.rich.fragment.RichPageTemplate;
import oracle.adf.view.rich.component.rich.fragment.RichRegion;
import
oracle.adf.view.rich.component.rich.nav.RichCommandNavigationItem;
import oracle.adf.view.rich.event.DialogEvent;
public TrainHandlerBean() {
}
/**
* Action method that is referenced from the train stop command
* action to defer train navigation and allow developers to
* interact with the user. In this sample a popup dialog is opened
* for the user to confirm train navigation.
*
* The use case for deferred trains top navigation includes manual
* complex field validation, to check for
* uncommitted data, e.g.
* ControllerContext.getInstance().getCurrentViewPort()
* .isDataDirty() , etc.
*
* @param actionEvent
*/
7
How-to defer train-stop navigation for custom form
ADF CODE CORNER validation or other developer interaction
(TaskFlowTrainStopModel)rni.getAttributes()
.get("trainStopNode");
String outcome = selectedTrainStop.getOutcome();
trainHandlerBeanHelper.setSelectedTrainStopOutcome(outcome);
/*
* ADD YOUR DEFERRED ACTION. FOR EXAMPLE, LAUNCH POPUP. TO
* CONTINUE THE TRAIN NAVIGATION, CALL
* queueTrainStopEventToRegion( ... )
*/
/**
* Method that finds the af:region container for a bounded task
* flow exposed in a region. Don't use this method outside of ADF
* regions.
* @param uiComponent Component within the region that is the
8
How-to defer train-stop navigation for custom form
ADF CODE CORNER validation or other developer interaction
/**
* In this sample the popup contains a dialog with OK, Cancel
* button.
* When OK is clicked, the train stop navigation should progress. If
* not, the train stop should not continue and remain on the current
* page
*
* @param dialogEvent
*/
public void onDialogAction(DialogEvent dialogEvent) {
//only if user confirmed navigation to the next train stop,
//perform navigation. Otherwise ignore request and remain
//on current train stop view
if (dialogEvent.getOutcome() == DialogEvent.Outcome.ok) {
//perform saved train stop navigation
queueTrainStopEventToRegion("#{viewScope.TrainHandlerBeanHelper
.getSelectedTrainStopOutcome}",
dialogEvent.getComponent());
}
}
/**
* Wrapper method around the RichRegion queueActionEventInRegion
* API.
* @param outcomeEL The EL to access a managed bean that returns
* the navigation string to to follow. This can be an outcome for a
* navigation case, or as in this sample, the implicit navigation
* case used in trains
*
* @param searchComponentInRegion To queue the action, we need a
9
How-to defer train-stop navigation for custom form
ADF CODE CORNER validation or other developer interaction
adfRegion =
this.findRichRegionContainer(searchComponentInRegion);
FacesContext fctx = FacesContext.getCurrentInstance();
ExpressionFactory expressionFactory =
fctx.getApplication().getExpressionFactory();
ELContext elctx = fctx.getELContext();
MethodExpression methodExpression =
expressionFactory.createMethodExpression(elctx,
outcomeEL,
String.class,
new Class[] { });
//queue action in region
adfRegion.queueActionEventInRegion(
methodExpression, null, null, false, 0, 0,
PhaseId.INVOKE_APPLICATION);
}
/**
* Managed bean property reference to a managed bean in view scope
* @param trainHandlerBeanHelper Managed bean inserted as a managed
* property reference
*/
public void setTrainHandlerBeanHelper(
TrainHandlerBeanHelper trainHandlerBeanHelper) {
this.trainHandlerBeanHelper = trainHandlerBeanHelper;
}
10
How-to defer train-stop navigation for custom form
ADF CODE CORNER validation or other developer interaction
This managed bean is just a helper class that saves the selected train node outcome value for later
navigation when the user confirms the popup dialog with Ok.
package adf.sample;
Sample Download
The Oracle JDeveloper 11.1.2.1 sample workspace is available as sample 97 from ADF Code Corner.
http://www.oracle.com/technetwork/developer-tools/adf/learnmore/index-101235.html
Though the sample is developed with JDeveloper 11g R2, the solution also works with previous versions
of Oracle JDeveloper 11g.
RELATED DOCOMENTATION
11
How-to defer train-stop navigation for custom form
ADF CODE CORNER validation or other developer interaction
12