I'm trying to pass a List of selected items into a Visual Workflow. I know that I have to iterate over the wrapper List, pull out each record, and add it to a new collection. My question is can I pass the variable into the Visual Workflow, and then iterate over it OR do i have to iterate over it in my controller, get my new collection, and THEN pass it into the Visual Workflow?

I guess can i pass a wrapper collection into Visual Workflow? If not, can someone provide a quick example of how I would iterate over it and add it to a new non-wrapper collection in my Controller?

Below is my controller:

public class RibbonClauseSearchControllerv2 {

    // the results from the search. do not init the results or a blank rows show up initially on page load
    public List<RibbonClauseWrapper> searchResults {get;set;}
    List<RibbonClause__c> ribbonClauseList;
    public List<RibbonClause__c> getRibbonClauseList() {
        return ribbonClauseList;
    // the categories that were checked/selected.
    public List<RibbonClauseWrapper> selectedRibbonClauses {
        get {
            if (selectedRibbonClauses == null) selectedRibbonClauses = new List<RibbonClauseWrapper>();
            return selectedRibbonClauses;

    // the text in the search box
    public string searchText {
        get {
            if (searchText == null) searchText = 'Type Value'; // prefill the search box for ease of use
            return searchText;

    // constructor
    public RibbonClauseSearchControllerv2() {}

    // fired when the search button is clicked
    public PageReference search() {

        if (searchResults == null) {
            searchResults = new List<RibbonClauseWrapper>(); // init the list if it is null
        } else {
            searchResults.clear(); // clear out the current results if they exist
        // Note: you could have achieved the same results as above by just using:
        // searchResults = new List<RibbonClauseWrapper>();

        // dynamic soql for fun
        String qry = 'Select rc.Name, rc.Id, rc.Text__c, rc.Clause_Name__c, rc.Additional_NST_Details__c From RibbonClause__c rc Where rc.Name LIKE \'%'+searchtext+'%\' Order By rc.Name';
        // may need to modify for governor limits??
        for(RibbonClause__c rc : Database.query(qry)) {
            // create a new wrapper by passing it the category in the constructor
            RibbonClauseWrapper rcw = new RibbonClauseWrapper(rc);
            // add the wrapper to the results
        return null;

    public PageReference next() {
        List<RibbonClause__c> ribbonclauseList = new List<RibbonClause__c>();

        // clear out the currently selected 
//        selectedRibbonClauses.clear();
//        ribbonclauseList.clear();

        // add the selected ribbonclause to a new List
        for (RibbonClauseWrapper rcw : searchResults) {
            if (rcw.checked)

//        // Now we have our list of selected contacts and can perform any type of logic we want, sending emails, updating a field on the Contact, etc
//        System.debug('These are the selected Ribbonclauses...' + ribbonclauseList);
//        for(RibbonClause__c rcf: ribbonclauseList) {
//            system.debug(rcf);
//        }
//       ribbonclauseList =null; // we need this line if we performed a write operation  because getContacts gets a fresh list now
         return Page.RibbonClause_Results;
//         return null;


    // fired when the back button is clicked
    public PageReference back() {
        return Page.RibbonClause_Search;

    // fired when no clause available button is clicked
    public PageReference noclause() {
        return Page.clauseKeyPage;

    public PageReference getListView() {
        return new PageReference('https://cs-iris--rksb1.cs17.my.salesforce.com/a1X?fcf=00Bg0000001HSu1');

public class ribbonClauseWrapper {

    public Boolean checked{get;set;}
    public RibbonClause__c rc{get;set;}

    public RibbonClauseWrapper(){
        rc = new RibbonClause__c();
        checked = false;

    public RibbonClauseWrapper(RibbonClause__c rc2){
        rc = rc2;
        checked = false;



This is my Visualforce Page that initiates the Flow.

<apex:page controller="RibbonClauseSearchControllerv2">  
    <apex:form >
        <apex:pageBlock rendered="True" >

            <apex:pageBlockButtons >
                <apex:commandButton action="{!back}" value="Back"/>
            <apex:pageMessages />

            <apex:pageBlockSection title="You Selected" columns="1" collapsible="true">
                <apex:pageBlockTable value="{!selectedRibbonClauses}" var="rc2" style="width:100%">
                    <apex:column value="{!rc2.rc.Name}" headerValue="Name" Style="width:100px"/>
                    <apex:column value="{!rc2.rc.Text__c}" headerValue="Language" Style="width:600px"/>
                    <apex:column value="{!rc2.rc.Id}" headerValue="Id" Style="width:1px" rendered="false" />


    <flow:interview name="Approval_Record_Creation" buttonLocation="top" finishLocation="{!ListView}">

    <apex:param name="cv_RibbonClauseId" value="{!ribbonClauseList}" />
    <apex:param name="v_UserId" value="{!$User.Id}"/>
    <apex:param name="vMId" value="{!$CurrentPage.parameters.Id}"/>

The parameter giving me trouble is

apex:param name="cv_RibbonClauseId" value="{!ribbonClauseList}"

When I hard code an ID for the value here then it passes into my flow fine.

I also ran a System.Debug in the controller for the ribbonClauseList in the controller. I commented it out in the controller that I've pasted here, but the snippet of it is below:

System.debug('These are the selected Ribbonclauses...' + ribbonclauseList);
      for(RibbonClause__c rcf: ribbonclauseList) {

In the Debug logs it shows records of type RibbonClause__c, so i know that the variable is being populated.....

So.. 1) I can hardcode a value in the VF page for the flow variable which comes through correctly in the floe and 2) I know that the variable I'm trying to pass into the flow is being populated with values... Can someone help me understand where the gap is that I'm missing?

  • Does your wrapped collection consist of SObject or Apex Object? You can put collection (list) of SObject as an input parameter to flow.
    – Roman
    Jul 12, 2017 at 9:28
  • it is an sObject
    – Clink
    Jul 12, 2017 at 13:19

1 Answer 1


To create an input variable in Visual Flow designer : go to Resource Tab, select SObject Collection Variable. In new window choose your Object Type and Input/Output Type.

See example bellow:


  • Thanks but when i try to pass in an sObject Collection Variable it gives me error "wrong data type"
    – Clink
    Jul 12, 2017 at 19:46
  • Please show you code and flow variable definition
    – Roman
    Jul 13, 2017 at 4:21

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .