Sunday, January 29, 2017

apex:input in visualforce components causes page to crash on rerender when referencing a wrapper class value (Updated with fix)

Too complicated to follow? Let me break it down...

1. I created a visualforce page
2. I created a component to contain some logic
3. I created a wrapper class to contain an instance of object and some related attributes, so that I could fetch and print a list of those objects in a dataTable/apex:repeat

Then, within the visualforce component:
4. I created a checkbox to rerender the page
5. Based on the selected value, it shows/hides the column containing the <apex:input> tag that references an integer attribute within the wrapper class

Behavior:
On checking/unchecking the checkbox, the presence of the <apex:input> tag referencing a wrapper class member causes the visualforce to crash

Workarounds:
1. Wrap <apex:inputCheckbox> within an <apex:ActionRegion> (kudos to Ana Esrich for finding this one... https://developer.salesforce.com/forums/ForumsMain?id=9060G000000I3jc )
2. Use apex:inputText instead of apex:input, or any other suitable alternative
3. Place the visualforce code directly in the visualforce page, instead of in a component



Here's some sample code:

Class


public class TestApexInput {
    
    public Class classWrapper {
        public Integer cwInt {get; set;}
        public Contact cwCont {get; set;}
        
        public classWrapper (Contact c) {
            cwCont = c;
            cwInt = 1;
        }
    }
    
    public TestApexInput () {
        
    }
    
    public List<classWrapper> listCW {
        get {
            if(listCW == null){
                listCW = new List<classWrapper>();
                
                for(Contact c: [Select Id, Name From Contact])
                    listCW.add(new ClassWrapper(c));
            }
            
            return listCW;
        } 
        set;
    }
    
    public Boolean chkbxAI {get {if(chkbxAI==null) chkbxAI = true; return chkBxAI; } set;}
    public Integer noncwInt {get; set;}

}

Sample Visualforce

<apex:page docType="html-5.0">
    <c:testapexcmp />

</apex:page>

Sample Component

<apex:component controller="TestApexInput">
        <apex:form id="testApexInputForm">
        <apex:inputcheckbox id="chkbxAI" value="{!chkbxAI}" >
            <apex:actionSupport reRender="testApexInputForm" id="actfunTAI" event="onclick"/>
        </apex:inputcheckbox>
   <table>
        <apex:repeat value="{!listCW}" var="cw" id="dtable">
            <tr>
           <td><apex:outputText value="{!cw.cwCont.Name}" /></td>
           <td><apex:outputText value="{!cw.cwCont.Id}" /></td>
           <td><apex:outputPanel rendered="{!chkbxAI}">
                <td><!--apex:input value="{!cw.cwInt}" type="number" id="apexInputInt"/--></td>
                <td><apex:input value="{!noncwInt}" type="number" id="apexInputnonCWInt"/></td>
                <td><apex:inputText value="{!cw.cwInt}" id="apexInputInt2"/></td>
           </apex:outputPanel></td>
            </tr>
    </apex:repeat>
    </table>
        Flag: {!chkbxAi}
    </apex:form>

</apex:component>

What this blog is for...

... nothing too exciting.

Just wanted to capture any Aha moments while working with Salesforce or other technologies that might help save other people time.

Cheers!