function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Martha VMartha V 

How to pass a table's row from Visualforce to a controller extension

I want to make a VF page that shows members of a campaign as well as has a searchfield to find contacts to add to the campaign. So the action for the search field will find all contacts that match and display them on a list. Then the user can select a contact and click on the name and that contact would be added to the campaign. 

My problem is that I don't know how to implement that last bit. Since the list of contats is displayed with a pageBlockTable how does the controller know which contact was selected.

Here is my VF page markup

<apex:page standardController="Campaign" extensions="showCampaignMembers">
  <apex:form >
    <apex:pageBlock title="{!campaign.name}">
      <apex:pageBlockSection title="Criteria">
      <apex:outputLabel value="Enter Name Snippet"/>
      <apex:inputText value="{!nameQuery}"/>
      <apex:commandButton action="{!executeSearch}" value="Search"/>
   </apex:pageBlockSection>
    
   <apex:pageBlockTable value="{!contacts}" var="con">
      <apex:column headerValue="Name">
         <apex:outputLink value="/{!con.id}/e?retURL={!URLENCODE('/apex/RetUrlSearchPage?query='+nameQuery)}">{!con.Name}</apex:outputLink>
      </apex:column>
      <apex:column value="{!con.Participant__c}"/>
   </apex:pageBlockTable>
   <apex:pageBlockSection title="Participants in Campaign">
     <apex:pageBlockTable value="{!participants}" var="part">
       <apex:column value="{!part.FirstName}"/>
       <apex:column value="{!part.LastName}"/>
       <apex:column value="{!part.Email}"/>
       <apex:column value="{!part.Status}"/>
                 
     </apex:pageBlockTable>
   </apex:pageBlockSection>
 </apex:pageBlock>
  </apex:form>
</apex:page>

-----------
And the controller
-----------

public class showCampaignMembers 
{
 public String nameQuery {get; set;}
 public List<Contact> contacts {get; set;}
 Public List<CampaignMember> participants {get; set;}
 private ApexPages.StandardController std;
 
 public PageReference executeSearch()
 {
  String queryStr='%' + nameQuery + '%';
  contacts=[select id, Name, Participant__c 
            from Contact 
            where name like :queryStr];
            
  return null;
 }
  
 public showCampaignMembers(ApexPages.StandardController stdCtrl)
 {
   Std = stdCtrl;
    Participants = [SELECT id, FirstName, LastName, Email, Status FROM CampaignMember
        WHERE CampaignId = :std.getId() ORDER BY FirstName];
  }

}

I appreciate any help.
Best Answer chosen by Martha V
AjazAjaz
Hi Martha,

Your requirement can be fulfilled by using a wrapper class. Below is the code example of a requirement where a list of accounts will be displayed on vf page along with a checkbox on each row. When user selects the particular records, the controller will have a all records but you can distinguish with the help of checkbox true and false.
 
<apex:page controller="AccountSelectClassController" sidebar="false">
    <script type="text/javascript">
        function selectAllCheckboxes(obj,receivedInputID){
            var inputCheckBox = document.getElementsByTagName("input");
            for(var i=0; i<inputCheckBox.length; i++){
                if(inputCheckBox[i].id.indexOf(receivedInputID)!=-1){
                    inputCheckBox[i].checked = obj.checked;
                }
            }
        }
    </script>
    <apex:form >
        <apex:pageBlock >
            <apex:pageBlockButtons >
                <apex:commandButton value="Show Selected Accounts" action="{!processSelected}" rerender="table2"/>
            </apex:pageBlockButtons>
 
            <apex:pageblockSection title="All Accounts" collapsible="false" columns="2">
 
                <apex:pageBlockTable value="{!wrapAccountList}" var="accWrap" id="table" title="All Accounts">
                    <apex:column >
                        <apex:facet name="header">
                            <apex:inputCheckbox onclick="selectAllCheckboxes(this,'inputId')"/>
                        </apex:facet>
                        <apex:inputCheckbox value="{!accWrap.selected}" id="inputId"/>
                    </apex:column>
                    <apex:column value="{!accWrap.acc.Name}" />
                    <apex:column value="{!accWrap.acc.BillingState}" />
                    <apex:column value="{!accWrap.acc.Phone}" />
                </apex:pageBlockTable>
 
                <apex:pageBlockTable value="{!selectedAccounts}" var="c" id="table2" title="Selected Accounts">
                    <apex:column value="{!c.Name}" headerValue="Account Name"/>
                    <apex:column value="{!c.BillingState}" headerValue="Billing State"/>
                    <apex:column value="{!c.Phone}" headerValue="Phone"/>
                </apex:pageBlockTable>
 
            </apex:pageblockSection>
        </apex:pageBlock>
    </apex:form>
 
</apex:page>
 
public class AccountSelectClassController{
 
    //Our collection of the class/wrapper objects wrapAccount
    public List<wrapAccount> wrapAccountList {get; set;}
    public List<Account> selectedAccounts{get;set;}
 
    public AccountSelectClassController(){
        if(wrapAccountList == null) {
            wrapAccountList = new List<wrapAccount>();
            for(Account a: [select Id, Name,BillingState, Website, Phone from Account limit 10]) {
                // As each Account is processed we create a new wrapAccount object and add it to the wrapAccountList
                wrapAccountList.add(new wrapAccount(a));
            }
        }
    }
 
    public void processSelected() {
    selectedAccounts = new List<Account>();
 
        for(wrapAccount wrapAccountObj : wrapAccountList) {
            if(wrapAccountObj.selected == true) {
                selectedAccounts.add(wrapAccountObj.acc);
            }
        }
    }
 
    // This is our wrapper/container class. In this example a wrapper class contains both the standard salesforce object Account and a Boolean value
    public class wrapAccount {
        public Account acc {get; set;}
        public Boolean selected {get; set;}
 
        public wrapAccount(Account a) {
            acc = a;
            selected = false;
        }
    }
}

Hit thumbsup if it helps

Regards,
Zaja.

All Answers

AjazAjaz
Hi Martha,

Your requirement can be fulfilled by using a wrapper class. Below is the code example of a requirement where a list of accounts will be displayed on vf page along with a checkbox on each row. When user selects the particular records, the controller will have a all records but you can distinguish with the help of checkbox true and false.
 
<apex:page controller="AccountSelectClassController" sidebar="false">
    <script type="text/javascript">
        function selectAllCheckboxes(obj,receivedInputID){
            var inputCheckBox = document.getElementsByTagName("input");
            for(var i=0; i<inputCheckBox.length; i++){
                if(inputCheckBox[i].id.indexOf(receivedInputID)!=-1){
                    inputCheckBox[i].checked = obj.checked;
                }
            }
        }
    </script>
    <apex:form >
        <apex:pageBlock >
            <apex:pageBlockButtons >
                <apex:commandButton value="Show Selected Accounts" action="{!processSelected}" rerender="table2"/>
            </apex:pageBlockButtons>
 
            <apex:pageblockSection title="All Accounts" collapsible="false" columns="2">
 
                <apex:pageBlockTable value="{!wrapAccountList}" var="accWrap" id="table" title="All Accounts">
                    <apex:column >
                        <apex:facet name="header">
                            <apex:inputCheckbox onclick="selectAllCheckboxes(this,'inputId')"/>
                        </apex:facet>
                        <apex:inputCheckbox value="{!accWrap.selected}" id="inputId"/>
                    </apex:column>
                    <apex:column value="{!accWrap.acc.Name}" />
                    <apex:column value="{!accWrap.acc.BillingState}" />
                    <apex:column value="{!accWrap.acc.Phone}" />
                </apex:pageBlockTable>
 
                <apex:pageBlockTable value="{!selectedAccounts}" var="c" id="table2" title="Selected Accounts">
                    <apex:column value="{!c.Name}" headerValue="Account Name"/>
                    <apex:column value="{!c.BillingState}" headerValue="Billing State"/>
                    <apex:column value="{!c.Phone}" headerValue="Phone"/>
                </apex:pageBlockTable>
 
            </apex:pageblockSection>
        </apex:pageBlock>
    </apex:form>
 
</apex:page>
 
public class AccountSelectClassController{
 
    //Our collection of the class/wrapper objects wrapAccount
    public List<wrapAccount> wrapAccountList {get; set;}
    public List<Account> selectedAccounts{get;set;}
 
    public AccountSelectClassController(){
        if(wrapAccountList == null) {
            wrapAccountList = new List<wrapAccount>();
            for(Account a: [select Id, Name,BillingState, Website, Phone from Account limit 10]) {
                // As each Account is processed we create a new wrapAccount object and add it to the wrapAccountList
                wrapAccountList.add(new wrapAccount(a));
            }
        }
    }
 
    public void processSelected() {
    selectedAccounts = new List<Account>();
 
        for(wrapAccount wrapAccountObj : wrapAccountList) {
            if(wrapAccountObj.selected == true) {
                selectedAccounts.add(wrapAccountObj.acc);
            }
        }
    }
 
    // This is our wrapper/container class. In this example a wrapper class contains both the standard salesforce object Account and a Boolean value
    public class wrapAccount {
        public Account acc {get; set;}
        public Boolean selected {get; set;}
 
        public wrapAccount(Account a) {
            acc = a;
            selected = false;
        }
    }
}

Hit thumbsup if it helps

Regards,
Zaja.
This was selected as the best answer
Martha VMartha V
Yes Zaja, this seems to be what I want. Thanks! I will see if I can adapt it to my controller.
Martha VMartha V
Thanks Zaja! it worked great.