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 '17 at 9:28
  • it is an sObject – Clink Jul 12 '17 at 13:19

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 '17 at 19:46
  • Please show you code and flow variable definition – Roman Jul 13 '17 at 4:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.