2

I have a Visualforce page that allows a user to setup as many records (custom object called "Override") on the page as they want and then on submit all of the rows are inserted into Salesforce via the controller.

The page was created years ago and whenever we needed to add an additional field to the page all I had to do was add the apex:column and bind an apex:inputField and it just worked great.

Now the requirements have changed and I need to add a boolean, ie: a checkbox bound to apex:inputCheckbox.

enter image description here

As long as the user waits until the end, after all of the Add Rows have been called, then it's fine, the checked value is set on the new Overrides that are created.

However if the user checks the box for Preferred, then clicks Add Row (which just adds another row at the bottom), the Preferred checkbox for any checked rows becomes unchecked.

For all other values, Override Date, Override Amount (and a bunch that I took off for this demo) the values she had set before the Add Row link was clicked are persisted (I assume through viewstate), but not the Preferred checkbox.

About the only thing I can find online about this is the recommendation to use a Wrapper for your object then have an isSelected bit to manage which ones are selected, but I've been working on that and can't figure out how to utilize it.

Here's what I have for my controller & wrapper so far:

public List<OverrideWrapper> wrappers {get; set;}
public static Integer toDelIdent {get; set;}
public static Integer addCount {get; set;}
private Integer nextIdent=0;

public class OverrideWrapper
{
    public Override__c ovr {get; set;}
    public boolean isSelected{ get; set; }  
    public Integer ident {get; set;}

    public OverrideWrapper(Integer inIdent)
    {
        ident=inIdent;
        isSelected = false;
        ovr=new Override__c();
    }
}  

public multiOverrideInsertControllerV2()
{
    wrappers=new List<OverrideWrapper>();
    wrappers.add(new OverrideWrapper(nextIdent++));
}

public void delRow()
{
    Integer toDelPos=-1;
    for (Integer idx=0; idx<wrappers.size(); idx++)
    {
        if (wrappers[idx].ident==toDelIdent)
        {
            toDelPos=idx;
        }
    }

    if (-1!=toDelPos)
    {
        wrappers.remove(toDelPos);
    }
}

public void addRow()
{
    for (OverrideWrapper ovrw : wrappers)
    {
        system.debug('#### Is Selected = ' + ovrw.isSelected); 
        system.debug('#### Deposit Date = ' + ovrw.ovr.Deposit_Date__c);            
        if(ovrw.isSelected) {
            ovrw.ovr.Preferred__c = true;
        }
    }
    wrappers.add(new OverrideWrapper(nextIdent++));
}

Notice in the addRow() method, those system.debug's return null for deposit date and false for isSelected.

Can anyone point me into how to manage the state of these checkboxes?

Visualforce page per comment:

<apex:pageBlockTable value="{!wrappers}" var="w" id="table"> 
     <apex:column headerValue="Identity" rendered="false" >
        <apex:outputText value="{!w.ident}"/>
     </apex:column>                              
    <apex:column headerValue="Override Date">                      
        <apex:inputField value="{!w.ovr.Override_Date__c}" required="true" />                          
    </apex:column>  
    <apex:column headerValue="Preferred">
        <apex:inputCheckbox value="{!w.ovr.Preferred__c}" selected="{!w.isSelected}" immediate="true"  />
    </apex:column>                        
    <apex:column headerValue="Override Amount">                    
        <apex:inputField value="{!w.ovr.Override_Amount__c}" required="true" styleClass="total" onchange="calcTotal()"  />                           
    </apex:column>   
    <apex:column headerValue="Action">
        <apex:commandButton value="Delete" action="{!delRow}" rerender="table" immediate="true">
            <apex:param name="toDelIdent" value="{!w.ident}" assignTo="{!toDelIdent}"/>
        </apex:commandButton>
    </apex:column>                                               
 </apex:pageBlockTable> 

Note I've tried a number of different combinations for value and selected properties:

value="{!w.ovr.Preferred__c}" selected="{!w.isSelected}"
  • Can you show us the Visualforce markup as well? The problem might well be there. – Jagular Jun 19 '14 at 21:47
  • Just updated with the visualforce markup. – codethrift Jun 20 '14 at 13:03
  • How did you get it to work please? I have a similar issue. – N.. Feb 10 '17 at 6:51
1

Wow, I don't know how to feel about this. The answer is, Don't use apex:inputCheckbox, always use apex:inputField when binding to a value on a controller. Apex will do the work of knowing it's a boolean and making it a checkbox.

Ouch, that was a bunch of time wasted.

Maybe someone could add this to the apex:inputCheckbox documentation, right after it says this: "Use this component to get user input for a controller method that does not correspond to a field on a Salesforce object." - to say, "If you're binding a checkbox to a controller, use apex:inputfield" and it will be rendered as a checkbox.

0

I have code that does something similar. I've added it below. I think the key difference is that I have not tied my VF checkbox to a field in the object. I'm not sure that's possible when working with a list of records. My checkbox is tied to a field in the wrapper object.

<apex:inputCheckbox value="{!LE.ToMarkResolved}" />

Looking over my code, I realize it is potentially confusing. The database object is LogEntry__c. The wrapper class is LogEntry. I've tried to add comments to clear up exactly what's being updated in key areas. Let me know if anything is not clear.

The function MarkResolved is where the selected objects are being updated.

I believe that the origin of my code is here

VF markup

<apex:pageBlockTable id="table" value="{!LogEntries}" var="LE" rows="75">
      <apex:column headerValue="Select Log Entries">
         <apex:inputCheckbox value="{!LE.ToMarkResolved}" />         
      </apex:column>      
      <apex:column headerValue="Site" value="{!LE.SiteProg}"/>

Wrapper class (not an inner class in this case so I can pass parameters)

//wrapper class LogEntry
// used in ManageLogEntries, LogEntryController, LogEntryValidator
//
public class LogEntry {
public Boolean checked{get;set;}  //checked in VF page
public String SiteProg{get; set;}
public Date MissingDay{get;set;}
public Boolean ToMarkResolved{get;set;} //missing attendance found (or we've decided to stop looking)

public LogEntry__c le{get;set;}

public LogEntry(String sp, Date dt, LogEntry__c l) {
   le = l;
   checked = false;
   ToMarkResolved = false;
   SiteProg = sp;
   MissingDay = dt;    
   }
}

controller code called from VF page

//*****************************************************************************
//
public PageReference MarkResolved() {
Date dt;
String msg;
List<LogEntry__c> ToResolve = new List<LogEntry__c>();   

List<String> dtmp;
if (AttendanceDateStr != '') {
    dtmp = AttendanceDateStr.Split('/');
    dt =  Date.newinstance(integer.valueof(dtmp[2]),integer.valueof(dtmp[0]),integer.valueof(dtmp[1]));
    }

for (LogEntry le : LogEntries) {
    if (le.ToMarkResolved == true){  // if the wrapper object is selected
   le.le.Is_Resolved__c = true;      // mark the LogEntry__c record as resolved
   ToResolve.add(le.le);
   }
}

//update the selected records.
If (ToResolve.size() > 0 ) {
    update ToResolve;               // update the list of selected LogEntry__c records
    }    

// update the list of displayed logentries
LogEntries = FindLogEntries();
return null;
}
  • I appreciate the help but this doesn't address the "addRow" nature of the problem. If I loop through the records and call insert, the checked boxes are checked accordingly and true saved. It's the round-trip of add rows that deselects the checkbox and messes things up. Maybe I'll have to do something on the client side to persist? – codethrift Jun 20 '14 at 17:13
  • Because "w.isSelected" is not bound to a field in the Visualforce page, its value never changes. You are only using it to set the initial value of your inputCheckbox. Thus, when you run through the rows, there will be no update. – Jagular Jun 20 '14 at 17:37

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.