Advanced Examples of Using <flow:interview>

The <flow:interview> component is designed to make it easy to develop complex Visualforce interactions. However, there are also more features you can access in your flow by creating a custom controller. With custom controllers, you can build a page with multiple components that can interact with each other. Any flow within your organization can be individually referenced by its own Apex type, and the variables in the flow can be accessed as member variables.

Note
You can only set variables that allow input access and get variables that allow output access. For each flow variable, input and output access is controlled by these fields:
  • Input/Output Type variable field in the Cloud Flow Designer
  • isInput and isOutput fields on FlowVariable in the Metadata API
For a variable that doesn’t allow input or output access, attempts to set or get the variable are ignored, and compilation may fail for the Visualforce page, its <apex:page> component, or the Apex class.
For our next example, the flow with unique name ”ModemTroubleShooting" is referenced as Flow.Interview.ModemTroubleShooting. The markup illustrates how to display a value of a flow variable in a different part of the page:
<apex:page Controller="ModemTroubleShootingCustomSimple" tabStyle="Case">
    <flow:interview name="ModemTroubleShooting" interview="{!myflow}"/>
    <apex:outputText value="Default Case Prioriy: {!casePriority}"/>
</apex:page>
Note
If the flow is from a managed package, then the name attribute must be in this format: namespace.flowuniquename.
The controller for the above markup looks like this:
public class ModemTroubleShootingCustomSimple {

    // Need not instantiate explicitly the Flow object using the class constructor
    public Flow.Interview.ModemTroubleShooting myflow { get; set; } public String casePriority; public String getcasePriority() { // Access flow variables as simple member variables with get/set methods
        if(myflow==null) return 'High'; else return myflow.vaCasePriority; } }

If you're using a custom controller, you can also set the initial values of the variables at the beginning of the flow in the constructor of the flow. Passing in variables using the constructor is optional and isn't necessary if you are using <apex:param> tags to set the value.

Here's an example of a custom controller that sets the values of flow variables in a constructor:
public class ModemTroubleShootingCustomSetVariables {
    public Flow.Interview.ModemTroubleShooting myflow { get; set; }
 
    public ModemTroubleShootingCustomSetVariables() {
        Map<String, Object> myMap = new Map<String, Object>();
        myMap.put('vaCaseNumber','123456');
        myflow = new Flow.Interview.ModemTroubleShooting(myMap);
    }
 
    public String caseNumber { set; }
    public String getcaseNumber() {
        return myflow.vaCaseNumber;
    }
}

You can use the getVariableValue method in the Flow.Interview class to enable a Visualforce controller to access the value of a flow variable. The variable may be in the flow embedded in the Visualforce page or in a separate flow that is called by a subflow element. The returned variable value comes from whichever flow the interview is currently running. If the specified variable can’t be found in that flow, the method returns null. This method checks for the existence of the variable at run time only, not at compile time.

The following sample uses the getVariableValue method to obtain breadcrumb (navigation) information from the flow embedded in the Visualforce page. If that flow contains subflow elements, and each of the referenced flows also contains a vaBreadCrumb variable, the Visualforce page can provide users with breadcrumbs regardless of which flow the interview is running.
public class SampleContoller {

   //Instance of the flow
   public Flow.Interview.Flow_Template_Gallery myFlow {get; set;} public String getBreadCrumb() { String aBreadCrumb; if (myFlow==null) { return 'Home';} else aBreadCrumb = (String) myFlow.getVariableValue('vaBreadCrumb'); return(aBreadCrumb==null ? 'Home': aBreadCrumb); } }
The following table shows the differences in the naming of supported data types between the flow and Apex.
FlowApex
TextString
NumberDecimal
CurrencyDecimal
DateDate, DateTime
BooleanBoolean
As it's a good practice to write tests against your Apex code, the following is a trivial example of writing a test class for ModemTroubleShootingCustomSetVariables:
@isTest
private class ModemTroubleShootingCustomSetVariablesTest {

    static testmethod void ModemTroubleShootingCustomSetVariablestests() {
        PageReference pageRef = Page.ModemTroubleShootingSetVariables;
        Test.setCurrentPage(pageRef);
        ModemTroubleShootingCustomSetVariables mytestController = 
            new ModemTroubleShootingCustomSetVariables();
        System.assertEquals(mytestController.getcaseNumber(), '01212212');
    }
}

Setting the reRender Attribute

By using the reRender attribute, the <flow:interview/> component re-renders the flow without refreshing the whole page:

<apex:page Controller="ModemTroubleShootingCustomSimple" tabStyle="Case">
    <flow:interview name="ModemTroubleShooting" interview="{!myflow}" 
     reRender="casePrioritySection"/> <apex:outputText id="casePrioritySection" 
     value="Default Case Prioriy: {!casePriority}"/> </apex:page>
Warning
If you don't set the reRender attribute, when you click a button to navigate to a different screen in a flow, the entire Visualforce page refreshes, not just the <flow:interview> component.
© Copyright 2000–2014 salesforce.com, inc. All rights reserved.
Various trademarks held by their respective owners.