Follow by Email

Wednesday, 10 February 2016

ADF Basics: Creating Bounded Task Flow Train using af:train component

This post is about using bounded task flow as train
A train presents a whole cycle and it's every stop presents a particular step of cycle
From the docs -

The train component presents a user with a series of stops, each stop representing a step in a multi-step process. The train walks the user through these steps, in a suggested order (the order being dictated by the underlying model). Each step is rendered as a train stop consisting of an image and a textual link indicating if they are in visited, current, unvisited and disabled states. Train can also be rendered in a vertical layout - the default being a horizontal layout. Trains are not rendered on printable pages. 

We can design bounded task flow as train flow , see how to configure this
  • Create a Fusion Web Application and a Bounded TaskFlow in view controller project
    File--->New---> From Gallery-->Web Tier--->JSF/Facelets-->ADF Taskflow

    Check Create Train checkbox-

  • Now drop two or more pages in BTF , i have dropped three view activities from component palette, these fragments will behave as train stops

  • Select a view and go to structure window , expand view node and right click on train stop select Insert Inside Train Stop --> Display Name

  • Put a name for that stop and follow same steps for all view activities, this name will appear on that stop when we run this

  • Next is to create fragment , double click on first view activity and create a jsp xml fragment , now drop af:train and af:trainButtonBar on page from component palette

  • Click on OK with default value

    Drop an output text on page and it's value is - First Stop, Now repeat these steps for each view activity and each fragment looks like this

  • Now drop this bounded task flow in a jspx page as region and run that page

  • On clicking Next button

All done :)
Now if we want to change train's default look then we can use af:navigationPane component , this component supports Apache Trinidad MenuModel ,that extends TreeModel and implemented by Train Model so we can directly use navigationPagewithout much efforts

af:navigationPane has af:commandNavigationItem as it's child component and it supports multiple UI hints as list, bar ,buttons, choice and tabs
See xml code to use af:navigationPane-

<af:navigationPane hint="list" id="np1" value="#{controllerContext.currentViewPort.taskFlowContext.trainModel}"
            <f:facet name="nodeStamp">
                <af:commandNavigationItem text="#{train.textAndAccessKey}" id="cni1" visited="#{train.visited}"
                                          disabled="#{train.disabled}" action="#{train.action}"/>

And see how it looks on page -
Select navigationPane on page and see in property inspector and change it's hints to see different looks of train

 Bar -
Cheers :) Happy Learning


  1. Is there a way I can know in which step of the train am I? I need to know -inside some bean method- in which step I am so I can take decisions to do other stuff

    1. Luis

      Check ADF Train TaskFlow
      There is a method used to determine whether rendered is current stop or not using navigation pane
      I think you can use this method to know train stop name (See complete article in the link)

      public boolean isCurrentTab() {
      //get access to the JSF context classes
      FacesContext fctx = FacesContext.getCurrentInstance();
      ELContext elctx = fctx.getELContext();
      Application app = fctx.getApplication();
      ExpressionFactory expressionFactory = app.getExpressionFactory();
      //train is the name of the variable attribute defined in //af:navigationPane
      ValueExpression ve = expressionFactory.createValueExpression(elctx, "#{train}", Object.class);
      //get the rendered stop's viewActivity
      TaskFlowTrainStopModel renderedTrainNode = (TaskFlowTrainStopModel) ve.getValue(elctx);
      //get current train stop to compare it with the current "rendered"
      //train stop
      ControllerContext controllerContext = ControllerContext.getInstance();
      ViewPortContext currentViewPortCtx = controllerContext.getCurrentViewPort();
      TaskFlowContext taskFlowCtx = currentViewPortCtx.getTaskFlowContext();
      TaskFlowTrainModel taskFlowTrainModel = taskFlowCtx.getTaskFlowTrainModel();
      //the train stop that is rendered in the train bar
      String renderedActivityId = renderedTrainNode.getLocalActivityId();
      //the train's current stop: the state
      TaskFlowTrainStopModel currentStop = taskFlowTrainModel.getCurrentStop();
      if (renderedActivityId.equalsIgnoreCase(currentStop.getLocalActivityId())) {
      return true;
      return false;