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
Shirley MaglioShirley Maglio 

How to add a checkbox next to each row of a table in Visualforce?

Hi,

I would like to know how to add a checkbox next to each row of a table in Visualforce?

Here is my Visualforce page:
<apex:page standardController="ProductEntity__c" recordSetVar=" listOfProductNotes " extensions="QRecords" >
     <apex:form >
     <apex:pageBlock title="Product Notes">
         <apex:pageBlockTable value="{!listOfProductNotes}" var="s">
               <apex:column value="{!s.ProductNotes__r.Name}"/>
         </apex:pageBlockTable>
     </apex:pageBlock>
     </apex:form>
</apex:page>
Any help is greatly appreciated!

Thanks,
Shirley Maglio
Ramu_SFDCRamu_SFDC
Follow the guidelines explained in the below article

https://developer.salesforce.com/page/Wrapper_Class
Shirley MaglioShirley Maglio
Ramu, Thank you for the link.  Shirley
Ashwin KhedekarAshwin Khedekar
/**
 * Controller for the VF page :- CheckboxDemoPage
 * It handles the processing of multiple opportunities selected using checkboxes on the VF page and updates the
 * Area__c custom field of these opportunities. It also uses pagination to handle the case of more than 1000
 * records cannot be shown at once in <apex:pageBlockTable> tag in the VF page. The wrapper class cOpportunity
 * will display the checkboxes due to its boolean field :- selected
 * Each wrapper class record will enclose one opportunity record along with its checkbox.
 */
global class CheckboxDemoCtlr
{
    public Id oppID {get;set;}
    private List<Opportunity> oppList;
    
    // To hold the current records pointed by StandardSetController of Opportunity
    public List<Opportunity> oppRecords{get;set;}
        
    // List of wrapper class records. Each wrapper class record will enclose 1 opportunity record along with its checkbox
    public List<cOpportunity> cOpportunityList{get;set;}

    public ApexPages.StandardSetController setCon{get;set;}
        
    public Integer recordCount {get;set;} // total queried records count
    public Integer currentPageNumber {get;set;} // current page number
    public Integer intPageSize;
    public Integer highestPageNumber {get;set;} // highest page number = 5 if 5 pages are there due to pagination, "Next" button clicking

    // Constructor                    
    public CheckboxDemoCtlr()
    {
        intPageSize = 4; // 4 records are to be shown on each page after pagination
        recordCount = 0;
        currentPageNumber = 0;
        highestPageNumber = 0;
        oppID = ApexPages.currentPage().getParameters().get('Id');
        
        oppList = [Select Id, Name, Area__c from Opportunity order by Name limit 50000];
        recordCount = oppList.size();
        highestPageNumber = calculateHighestPageNumber(recordCount);    
        if(recordCount > 0)
        {
            currentPageNumber = 1;
            oppRecords = new List<Opportunity>();
            setCon = new ApexPages.StandardSetController(oppList); // get the StandardSetController for Opportunity
            
            setCon.setPageSize(4);
            oppRecords = (List<Opportunity>)setCon.getRecords(); // get the records

            // Create new list of wrapper class records
            cOpportunityList = new List<cOpportunity>();
            
            for(Opportunity oppObj : oppRecords)
            {
                cOpportunityList.add(new cOpportunity(oppObj));
            }
        }
    }
  
    public pageReference processSelected()
    {
        List<Opportunity> selectedOpp = new List<Opportunity>();
        Integer counterCurrentPageNumber = 1;
        counterCurrentPageNumber = currentPageNumber;
                        
        for(cOpportunity cOpp : cOpportunityList)
        {
            if(cOpp.selected == true) // this checkbox is checked, so process this opportunity
            {
                selectedOpp.add(cOpp.opp);                
            }
        }   
        
        if(selectedOpp.size() > 0)
        {
            for(Opportunity oppObj : selectedOpp)
            {
                oppObj.Area__c = 'this opp got processed';
                
                // Display_current_page_number__c is a field of type Text
                oppObj.Display_current_page_number__c = String.valueOf(currentPageNumber);
                
                // Display_highest_page_number__c is a field of type Text
                oppObj.Display_highest_page_number__c = String.valueOf(highestPageNumber);
            }
            update selectedOpp;
            
            // For avoiding error :- Modified rows exist in the records collection :-
            // Query records again to display them in the pageBlockTable
            oppList = [Select Id, Name, Area__c from Opportunity order by Name limit 50000];
            recordCount = oppList.size();
            highestPageNumber = calculateHighestPageNumber(recordCount);
            
            oppRecords = new List<Opportunity>();
            setCon = new ApexPages.StandardSetController(oppList);
            
            setCon.setPageSize(4);
            oppRecords = (List<Opportunity>)setCon.getRecords();
            cOpportunityList = new List<cOpportunity>();
            
            for(Opportunity oppObj : oppRecords)
            {
                cOpportunityList.add(new cOpportunity(oppObj));
            }

            // Start counting from page 1 again            
            currentPageNumber = 1;
                
            // Got to navigate till counterCurrentPageNumber to show same page again, it could be the 2nd or 3rd page,
            // on which "Update Area" was clicked after selecting opportunities using checkboxes.
            // Keep calling :- moveNext();
            while(currentPageNumber < counterCurrentPageNumber)
            {
                moveNext();
            }
            
            // Show how many opportunities updated count on VF page
            if(selectedOpp.size() > 1)
            {    
                ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.INFO,'Updated ' + selectedOpp.size() + ' opportunities'));
            }
            else
            {
                ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.INFO,'Updated ' + selectedOpp.size() + ' opportunity'));
            }
        }
        return null;
    }
    
    public void moveNext()
    {
        if(setCon.getHasNext())
        {
            oppRecords = new List<Opportunity>();
            setCon.next();
            
            // Keep track of current page number
            if(currentPageNumber < highestPageNumber)
            {
                currentPageNumber = currentPageNumber + 1;
            }
                
            oppRecords = (List<Opportunity>)setCon.getRecords();

            // Create the wrapper class (cOpportunity) records to be shown on UI
            cOpportunityList = new List<cOpportunity>();
            for(Opportunity oppObj : oppRecords)
            {
                cOpportunityList.add(new cOpportunity(oppObj));
            }
        }
    }
        
    public void movePrevious()
    {
        if(setCon.getHasPrevious())
        {
            oppRecords = new List<Opportunity>();
            setCon.previous();
                
            if(currentPageNumber > 1)
            {
                currentPageNumber = currentPageNumber - 1;
            }
                    
            oppRecords = (List<Opportunity>)setCon.getRecords();
            cOpportunityList = new List<cOpportunity>();
            for(Opportunity oppObj : oppRecords)
            {
                cOpportunityList.add(new cOpportunity(oppObj));
            }
        }
    }
        
    public void moveFirst()
    {
        oppRecords = new List<Opportunity>();
        setCon.first();
        currentPageNumber = 1;
        oppRecords = (List<Opportunity>)setCon.getRecords();
        cOpportunityList = new List<cOpportunity>();
        for(Opportunity oppObj : oppRecords)
        {
            cOpportunityList.add(new cOpportunity(oppObj));
        }
    }
        
    public void moveLast()
    {
        oppRecords = new List<Opportunity>();
        setCon.last();
        currentPageNumber = highestPageNumber;
        oppRecords = (List<Opportunity>)setCon.getRecords();
        cOpportunityList = new List<cOpportunity>();
        for(Opportunity oppObj : oppRecords)
        {
            cOpportunityList.add(new cOpportunity(oppObj));
        }
    }

    // This wrapper class will show the checkbox for each opportunity through its "selected" boolean field
    public class cOpportunity
    {
        public Opportunity opp {get;set;}
        public Boolean selected {get;set;}
        
        public cOpportunity(Opportunity o)
        {
            opp = o;
            selected = false;
        }
    }
 
    // Get the highest page number. Highest page number is 5 if 5 pages exist due to pagination (Next button clicking).
    public Integer calculateHighestPageNumber(Integer recordCount)
    {
        if(math.mod(recordCount,intPageSize) != 0) // check for remainder is zero
        {
            Integer modResult = recordCount/intPageSize; // get the quotient
            return (modResult + 1);
        }
        else
        {
            return recordCount/intPageSize; // return quotient if record count is exactly
                // divisible by page size of records to be shown on each page (pagination)
        }
    }
}

<!--
  VF page :- CheckboxDemoPage
  Browse for this page using URL :-
  https://c.ap5.visual.force.com/apex/CheckboxDemoPage?id=0067F00000IOlJj
  where 0067F00000IOlJj is the ID of any opportunity record. Select checkboxes on left side for any opportunity records
  and click on "Update Area".
  The "Area__c" custom field of these opportunities will get populated with the text :- "this opp got processed".
  Click "Next" or "Last" as you wish.
  Select multiple opportunities on each screen using the checkboxes on the left side and click on "Update Area".
  The "Area__c" custom field of these opportunities will get populated.
-->

<apex:page controller="CheckboxDemoCtlr" sidebar="false" showHeader="false" cache="false">
  <apex:form >
    <!-- For showing how many opportunities updated count -->
    <apex:pageMessages id="ResultMessages"/>

    <apex:outputPanel id="EnclosingPanel">
      <apex:outputPanel id="PanelOpp" rendered="{!cOpportunityList.size>0}">
        <apex:pageBlock >
          <apex:pageBlockButtons >
            <apex:commandButton value="Update Area" action="{!processSelected}" reRender="EnclosingPanel,ResultMessages"/>
          </apex:pageBlockButtons>
            
          <!-- Display the wrapper class records -->
          <apex:pageBlockTable value="{!cOpportunityList}" var="cOpp">
          
            <!-- The checkbox in the wrapper class -->  
            <apex:column >
              <apex:inputCheckbox value="{!cOpp.selected}"/>
            </apex:column>
            
            <apex:column title="Opportunity ID" value="{!cOpp.opp.Id}"/>
            <apex:column title="Opportunity Name" value="{!cOpp.opp.Name}"/>
            <apex:column title="Area" value="{!cOpp.opp.Area__c}"/>
          </apex:pageBlockTable>
          
          <apex:pageBlockSection>
            <apex:pageBlockSectionItem>
              <apex:outputpanel>
                <apex:commandButton action="{!moveFirst}" value="First" disabled="{!!setCon.hasPrevious}"/>
                <apex:commandButton action="{!movePrevious}" value="Previous" disabled="{!!setCon.hasPrevious}"/>
                <apex:commandButton action="{!moveNext}" value="Next" disabled="{!!setCon.hasNext}"/>
                <apex:commandButton action="{!moveLast}" value="Last" disabled="{!!setCon.hasNext}"/>
                
                <br/>
                Highest page number:
                <apex:outputText value="{!highestPageNumber}"/>
                
                <br/>
                Current page number:
                <apex:outputText value="{!currentPageNumber}"/>
                
                <br/>
                Total queried records: <apex:outputText value="{!recordCount}"/>
            
              </apex:outputpanel>
            </apex:pageBlockSectionItem>
          </apex:pageBlockSection>
                
        </apex:pageBlock>
      </apex:outputPanel>
      <apex:outputPanel id="PanelOpp2" rendered="{!cOpportunityList.size=0}">
        <apex:outputText value="No opportunities found" style="color:red;font-weight:bold"/>
      </apex:outputPanel>
    </apex:outputPanel>
  </apex:form>
</apex:page>