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
Greg CooganGreg Coogan 

Visualforce Checkbox in Custom Controller

I have written a custom controller and Visualforce page that displays records from a custom object, and related records, in a few HTML tables. I have a checkbox on the page and a Save button to display the refined results. Do I need to write a function that returns a modified list of records, basically copying what is in my controller's main class to a "PageReference save()" class? Ideally, the button would result in the controller running again with the updated value of the checkbox. I've seen examples but having trouble. Please help.
Best Answer chosen by Greg Coogan
LBKLBK
Hi Greg,

I  have made some minor changes in your controller class to call the data fetching in both constructor as well as Save() method.

Here  is the code.
public class TestCaseController {
        
    public class Lists{
        public Test_Case__c testcase{get;set;}
        public List<Related_Test_Record__c> test1{get;set;}
        public Lists(){
            this.testcase = new Test_Case__c();
			this.test1 = new List<Related_Test_Record__c>();
        }
    }
    
    public List<Lists> lstList{get;set;}
    //public List<Lists> lstTestCases{get;set;}
    public List<Lists> lstTest1{get;set;}  
    public Boolean cbTest{get;set;}
    
    public PageReference save(){
        fetchData();
		return null;
    }
    
	public TestCaseController(){
		if(cbTest == null)
			cbTest = false;
			
		if(lstList == null)
			lstList = new List<Lists>();
		//lstTestCases = new List<Lists>();

		fetchData();
	}
    public void fetchData(){
        //cbTest = System.currentPageReference().getParameters().get('cbTest');

        List<Test_Case__c> lstTestCases = [SELECT Id, Name,
                RecordType.Name, Status__c
                (SELECT Id FROM Related_Test_Record__c),
                FROM Test_Case__c];
        if(lstTestCases.size()>0){
            for(Test_Case__c testcase:lstTestCases){
                Lists lst = new Lists();
                lst.testcase = testcase;
                if(testcase.Related_Test_Record__r.size() > 0){
                    lst.test1 = testcase.Related_Test_Record__r;
                }
                if(cbTest == true && testcase.Top_List__c == true){
                    lstList.add(lst);
				//cbTest == null is included because I wanted records to render even if my custom checkbox isn't passing a value currently
                } else if(cbTest == false){
                	lstList.add(lst);
                }
            }
        }
    }    
}

And, I suggest you use reRender option on the Save button, to rerender your second section.

Line 26 of your VF page would be like this.
 
<apex:pageBlock title="Case Report" id="CaseReport">
And, line 21 would be..
<apex:commandButton action="{!save}" value="Update Report" rerender="CaseReport"/>

Let me know if this works for you.

 

All Answers

LBKLBK
When the checkbox value changes, does it impact the related records displayed in the page?

If yes, you need to reload the data. Otherwise, you can simply save the data and return null from your save() method, so that it will not refresh the screen.

Can you please post your code, if you need help resolving any errors?
Greg CooganGreg Coogan
LBK,

I was originally going to have OnClick or OnChange Javascript function but then realized the button made more sense since I'll be adding more criteria options, like data ranges. I have a repeat section on the Visualforce page that has a main table that displays fields of a single record and three small tables below that display related records of that single record. This repeats for all records in a list passed from the Controller. The criteria would affect all of these tables since they are nested in a repeat for each record.

The Save method is basically a "re-run report" function. It never saves data.

Currently, the Save method returns null (does nothing) and refreshes the page.

Here is an anonymized version of my code (cannot post the actual code I'm developing for my company):

Visualforce:
<apex:page controller="TestCaseController" docType="html-5.0">
    <style>
        table {
    		border-collapse: collapse;
        	width: 100%;
        }
        tr.dataRow { 
        	background-color:white; 
        }
        tr.dataRow:hover { 
        	background-color: #e3f3ff;
        };
    </style>
    <apex:form id="updateReportOptions">
    	<apex:pageBlock title="Report Options">
            <apex:pageBlockSection >
            	<apex:inputCheckbox id="cbTest" label="Top List Only" value="{!cbTest}">
                    <!-- <apex:actionSupport event="onchange" reRender="displayReport"/> -->
                    <apex:actionFunction name="cbTest" action="{!save}"/>
                </apex:inputCheckbox>
                <apex:commandButton action="{!save}" value="Update Report"/>
            </apex:pageBlockSection>
    	</apex:pageBlock>
    </apex:form>
    <apex:form id="displayReport">
        <apex:pageBlock title="Case Report">
            
            <apex:repeat value="{!lstList}" var="lst">
                <table class="list" border="0">
                    <tr class="headerRow">
                        <th class="headerRow">Case #</th>
                        <th class="headerRow">Case Type</th>
                        <th class="headerRow">Status</th>
                    </tr>
                    <tr class="dataRow">
                        <td class="dataCell">
                            <apex:outputLink value="/{!lst.testcase.Id}">{!lst.testcase.Name}</apex:outputLink>                        
                        </td>
                        <td class="dataCell">{!lst.testcase.RecordType.Name}</td>
                        <td class="dataCell">{!lst.testcase.Status__c}</td>
                        <td class="dataCell">
                            <apex:outputText value="{!IF(lst.testcase.Top_List__c,'Yes','No')}"></apex:outputText>
                        </td>
                    </tr>            
                </table>
                <br/>
                <table>
                    <tr>
                        <td style="width:100%">                            
                            <table class="list" border="0">
                                <tr class="headerRow">
                                    <th class="headerRow">Id</th>
                                    <th class="headerRow">Relationship</th>
                                </tr>
                                <apex:repeat value="{!lst.test1}" var="testRelated" rendered="{!lst.test1.size > 0}">
                                    <tr class="dataRow">
                                        <td class="dataCell">
                                            <apex:outputLink value="/{!testRelated.Id}">{!testRelated.Id}</apex:outputLink>                                        
                                        </td>
                                    </tr>
                                </apex:repeat>
                                <apex:outputPanel rendered="{!lst.test1.size == 0}">
                                    <tr class="dataRow">
                                        <td colspan="100%">No Related Test Record.</td>
                                    </tr>
                                </apex:outputPanel>
                            </table>
                        </td>
                    </tr>
                </table>
                <br/>
                <br/>
                <br/>
            </apex:repeat>
            
        </apex:pageBlock>
	</apex:form>
</apex:page>

Apex Custom Controller:
public class TestCaseController {
        
    public class Lists{
        public Test_Case__c testcase{get;set;}
        public List<Related_Test_Record__c> test1{get;set;}
        public Lists(){
            this.testcase = new Test_Case__c();
			this.test1 = new List<Related_Test_Record__c>();
        }
    }
    
    public List<Lists> lstList{get;set;}
    
    public List<Lists> lstTestCases{get;set;}
    public List<Lists> lstTest1{get;set;}
    
    public Boolean cbTest{get;set;}
    
    public PageReference save(){
        return null;
    }
    
    public TestCaseController(){
        //cbTest = System.currentPageReference().getParameters().get('cbTest');

        lstList = new List<Lists>();
        List<Test_Case__c> lstTestCases = [SELECT Id, Name,
                RecordType.Name, Status__c
                (SELECT Id FROM Related_Test_Record__c),
                FROM Test_Case__c];
        if(lstTestCases.size()>0){
            for(Test_Case__c testcase:lstTestCases){
                Lists lst = new Lists();
                lst.testcase = testcase;
                if(testcase.Related_Test_Record__r.size() > 0){
                    lst.test1 = testcase.Related_Test_Record__r;
                }
                if(cbTest == true && testcase.Top_List__c == true){
                    lstList.add(lst);
				//cbTest == null is included because I wanted records to render even if my custom checkbox isn't passing a value currently
                } else if(cbTest == false || cbTest == null){
                	lstList.add(lst);
                }
            }
        }
    }
    
}
I might be having the most trouble passing over a value. Line 38 of my controller is where I'd like to be able to use the checkbox value whenever Ioad and refresh the page.

The save function might not be needed if I can get the value of the checkbox to be passed to the main class of the Controller on refresh.
 
Greg CooganGreg Coogan
You can ignore line 53 from Visualforce code. That is a header from a field I removed.
LBKLBK
Hi Greg,

I  have made some minor changes in your controller class to call the data fetching in both constructor as well as Save() method.

Here  is the code.
public class TestCaseController {
        
    public class Lists{
        public Test_Case__c testcase{get;set;}
        public List<Related_Test_Record__c> test1{get;set;}
        public Lists(){
            this.testcase = new Test_Case__c();
			this.test1 = new List<Related_Test_Record__c>();
        }
    }
    
    public List<Lists> lstList{get;set;}
    //public List<Lists> lstTestCases{get;set;}
    public List<Lists> lstTest1{get;set;}  
    public Boolean cbTest{get;set;}
    
    public PageReference save(){
        fetchData();
		return null;
    }
    
	public TestCaseController(){
		if(cbTest == null)
			cbTest = false;
			
		if(lstList == null)
			lstList = new List<Lists>();
		//lstTestCases = new List<Lists>();

		fetchData();
	}
    public void fetchData(){
        //cbTest = System.currentPageReference().getParameters().get('cbTest');

        List<Test_Case__c> lstTestCases = [SELECT Id, Name,
                RecordType.Name, Status__c
                (SELECT Id FROM Related_Test_Record__c),
                FROM Test_Case__c];
        if(lstTestCases.size()>0){
            for(Test_Case__c testcase:lstTestCases){
                Lists lst = new Lists();
                lst.testcase = testcase;
                if(testcase.Related_Test_Record__r.size() > 0){
                    lst.test1 = testcase.Related_Test_Record__r;
                }
                if(cbTest == true && testcase.Top_List__c == true){
                    lstList.add(lst);
				//cbTest == null is included because I wanted records to render even if my custom checkbox isn't passing a value currently
                } else if(cbTest == false){
                	lstList.add(lst);
                }
            }
        }
    }    
}

And, I suggest you use reRender option on the Save button, to rerender your second section.

Line 26 of your VF page would be like this.
 
<apex:pageBlock title="Case Report" id="CaseReport">
And, line 21 would be..
<apex:commandButton action="{!save}" value="Update Report" rerender="CaseReport"/>

Let me know if this works for you.

 
This was selected as the best answer
Greg CooganGreg Coogan
It works, thank you!

Also, I added on line 34:
lstList.clear();
Without this line, fetchData() kept adding onto the list each time I clicked the button, resulting in duplicate records displayed.