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
Roger PavelleRoger Pavelle 

Errors calling function

I am writing a controller class that will capture the values of multiple checkboxes and rerender a result set based on those values.  To do this, I created an internal list of boolean values which correspond to the check boxes on the Apex form.  When a checkbox value changes, I call a function in the controller, passing along the corresponding check box number.  The function then reverses the value (true becomes false, false becomes true).  I then rerender the results based on this value change.

I've tried this multiple ways and am getting errors for reasons I don't understand.  Can someone please explain where my logic or understanding is faulty?

VF code (function to change the saved value of the checkbox - chkBoxValues is the list holding the values, all of which are initially false):
    public void chkBoxValue(Integer boxNum)
    {
        chkBoxValues[boxNum] = !chkBoxValues[boxNum];
    }

Apex code:
1)   <apex:inputCheckbox title="Choice" label="Choice" onchange="{! chkBoxValue(0) }" />
             <apex:commandLink reRender="bolete_list"/>
result:  unknown function chkBoxValue.  Check spelling

2)  <apex:inputCheckbox  label="Good">
          <apex:commandLink action="{! SetChkBoxValue(1) }" reRender="bolete_list"/>
     </apex:inputCheckbox>/>
result:  The content of elements must consist of well-formed character data or markup
Best Answer chosen by Roger Pavelle
Daniel BallingerDaniel Ballinger
Here is a simplified example of how to toggle the boolean values. Note how the actionScript parameter is being extracted from the page reference.

Visualforce page:
<apex:page setup="false" controller="BoleteController">
    <apex:form >
        <apex:pageBlock title="Bolete List" id="bolete_list">
            
            <apex:outputText>{!currentChkBoxValues}</apex:outputText>
       
            <apex:inputCheckbox label="Choice" id="choiceCheckbox" >
                <apex:actionSupport action="{!setChkBoxValue}" event="onclick" rerender="bolete_list">
                    <apex:param name="boxNum" value="1"/>
                </apex:actionSupport>
            </apex:inputCheckbox>
            
        </apex:pageBlock>
    </apex:form>
</apex:page>


Apex Controller:
public class BoleteController
{
    private List<Boolean> chkBoxValues = new List<Boolean>{false,false,false,false,false,false,false,false,false};
        
   
    public string currentChkBoxValues {
        get { 
            return string.join(chkBoxValues, ', '); 
        }
    }
    
    public void setChkBoxValue() {
        integer boxNum = integer.valueOf(system.currentPageReference().getParameters().get('boxNum'));
        setChkBoxValue(boxnum);
    }
       
    public void setChkBoxValue(Integer boxNum) {
        boolean before = chkBoxValues[boxNum];
        chkBoxValues[boxNum] = !chkBoxValues[boxNum];
        System.debug('boxNum:' + boxNum + ' before:' + before);
        System.debug(currentChkBoxValues);
    }
   
}


 

All Answers

Daniel BallingerDaniel Ballinger

Try using an apex:actionSupport (https://developer.salesforce.com/docs/atlas.en-us.pages.meta/pages/pages_compref_actionSupport.htm).

It would be something like:

<apex:inputCheckbox label="Choice" id="choiceCheckbox" >
                    <apex:actionSupport action="{!chkBoxValue}" event="onclick" rerender="bolete_list">
                                        <apex:param name="boxNum" value="1"/>
                    </apex:actionSupport>
</apex:inputCheckbox>
Roger PavelleRoger Pavelle
I tried this and still get the same result (unknown method Controller.chkBoxValue).  I also tried changing the function name from chkBoxValue to setChkBoxValue, but this made no difference.
Daniel BallingerDaniel Ballinger

Hi Roger, 

Can you provide some more content from your controller class and Apex page. You shouldn't need to prefix the method name with 'set'

Roger PavelleRoger Pavelle
Here's the Apex page showing both variations on the check boxes.  Once I figure out how to get them to work I'll be adding a lot more.:
<apex:page setup="false" controller="BoleteController">
    <apex:form >
        <apex:pageBlock title="Bolete List" id="bolete_list">
            <apex:inputCheckbox label="Choice" id="choiceCheckbox" >
                <apex:actionSupport action="{!setchkBoxValue}" event="onclick" rerender="bolete_list">
                    <apex:param name="boxNum" value="1"/>
                </apex:actionSupport>
            </apex:inputCheckbox>


                <apex:inputCheckbox  label="Good">
                <apex:commandLink action="{! SetChkBoxValue(1) }" reRender="bolete_list"/>
                </apex:inputCheckbox>/>

                <apex:inputCheckbox  label="Iffy">
                <apex:commandLink action="{! SetChkBoxValue(2) }" reRender="bolete_list"/>
                </apex:inputCheckbox>/>
                <apex:inputCheckbox  label="Avoid">
                <apex:commandLink action="{! SetChkBoxValue(3) }" reRender="bolete_list"/>
                </apex:inputCheckbox>/>

            <!-- bolete search result list -->
            <apex:pageBlock title="Search Results">
                <apex:pageBlockTable value="{! Boletes }" var="bol">
                    <apex:column value="{! bol.genus__c }">
                        <apex:facet name="header">
                            <apex:commandLink action="{! sortByGenus }" reRender="bolete_list">Genus
                            </apex:commandLink>
                        </apex:facet>
                    </apex:column>
                   
                    <apex:column value="{! bol.species__c }">
                        <apex:facet name="header">
                            <apex:commandLink action="{! sortBySpecies }" reRender="bolete_list">Species
                            </apex:commandLink>
                        </apex:facet>
                    </apex:column>
                   
                    <apex:column value="{! bol.Common__c }"/>
                </apex:pageBlockTable>
            </apex:pageBlock>
        </apex:pageBlock>
    </apex:form>
</apex:page>


Here's the controller class (minus some extraneous stuff like all the possible values and the sorting functions)
public class BoleteController
{
    private String sortOrder = 'Genus__c, Species__c ';
    private String whereClause = '';
    private List<Boolean> chkBoxValues = new List<Boolean>{false,false,false,false,false,false,false,false,false,};
    private List<String> whereClauseValues = new List<String>{'edibilityChoice', 'edibilityGood', 'edibilityIffy', 'edibilityAvoid', };
   
    public List<Bolete__c> getBoletes()
    {
        buildWhereClause();
        List<Bolete__c> results = Database.query(
            'SELECT Genus__c, Species__c, Common__c ' +
            'FROM Bolete__c ' +
            whereClause +
            'ORDER BY ' + sortOrder
        );
        return results;
    }
     
    public void setChkBoxValue(Integer boxNum)
    {
        chkBoxValues[boxNum] = !chkBoxValues[boxNum];
    }

   
    private void buildWhereClause()
    {
        Boolean exists = false;
        whereClause = '';
       
        //The first four values are for edibility, which are not mutually exclusive, so they are built
        // using or instead of and
        for (Integer i = 0; i<4; i++)
        {
            if (chkBoxValues[i])
            {
                if (exists)
                {
                    whereClause = whereClause + 'or ' + whereClauseValues[i] + ' = true ';
                }
                else
                {
                    whereClause = 'Where (' + whereClauseValues[i] + ' = true ';
                    exists = true;
                }
            }
        }
        if (exists)
        {
            whereClause = whereClause + ') ';
        }
       
        //All the other values are individual values, so they are built with AND
        for (Integer i = 4; i<57; i++)
        {
            if (chkBoxValues[i])
            {
                if (exists)
                {
                    whereClause = whereClause + 'and ' + whereClauseValues[i] + ' = true ';
                }
                else
                {
                    whereClause = 'Where (' + whereClauseValues[i] + ' = true ';
                    exists = true;
                }
            }
           
        }
    }
   
}
Daniel BallingerDaniel Ballinger
Here is a simplified example of how to toggle the boolean values. Note how the actionScript parameter is being extracted from the page reference.

Visualforce page:
<apex:page setup="false" controller="BoleteController">
    <apex:form >
        <apex:pageBlock title="Bolete List" id="bolete_list">
            
            <apex:outputText>{!currentChkBoxValues}</apex:outputText>
       
            <apex:inputCheckbox label="Choice" id="choiceCheckbox" >
                <apex:actionSupport action="{!setChkBoxValue}" event="onclick" rerender="bolete_list">
                    <apex:param name="boxNum" value="1"/>
                </apex:actionSupport>
            </apex:inputCheckbox>
            
        </apex:pageBlock>
    </apex:form>
</apex:page>


Apex Controller:
public class BoleteController
{
    private List<Boolean> chkBoxValues = new List<Boolean>{false,false,false,false,false,false,false,false,false};
        
   
    public string currentChkBoxValues {
        get { 
            return string.join(chkBoxValues, ', '); 
        }
    }
    
    public void setChkBoxValue() {
        integer boxNum = integer.valueOf(system.currentPageReference().getParameters().get('boxNum'));
        setChkBoxValue(boxnum);
    }
       
    public void setChkBoxValue(Integer boxNum) {
        boolean before = chkBoxValues[boxNum];
        chkBoxValues[boxNum] = !chkBoxValues[boxNum];
        System.debug('boxNum:' + boxNum + ' before:' + before);
        System.debug(currentChkBoxValues);
    }
   
}


 
This was selected as the best answer
Roger PavelleRoger Pavelle
Thanks!  This works like a charm.
BTW, I'm assuming the outputText and associated code are just for debugging purposes, correct?
Daniel BallingerDaniel Ballinger
No problem. Yes, those were just to make the simplified code easier to test/demo.