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
justinhowell82justinhowell82 

wrapper class and viewstate

I followed the simple code from the tech docs (https://developer.salesforce.com/page/Wrapper_Class) to create a page with editable pageblocktable that allows inline editing and the ability for used to select multiple records and perform specific actions on the selected.  Works great unitl I have a very large list and i was getting an error on the VF page that I've exceeded the max viewstate size.  In the linked tech doc there is a public property that is a list of the wrapper object:

03   //Our collection of the class/wrapper objects cContact
04   public List<cContact> contactList {get; set;}

The contactList which is what the pageblocktable is bound to is what was blowing up my viewstate but I am only getting the needed values in the SOQL to populate.  I did not think this would work but I changed it from public to transient which made it dissappear from viewstate as expected AND the form contiunes to work as designed.  I guess I was not expecting this to work due to the fact that that data is not stored in viewstate but it does appear ot be working.  I can still edit all the inputfield values line by line and call my save method which envokes the standard SF validation and everything still functions as before.  Can anyone shine some light on this for me?

Thanks,
Jsutin
James LoghryJames Loghry
Can you post the rest of your controller?  Seems strange that the form still works even though you've set your variable(s) to transient.
justinhowell82justinhowell82
controller:
public class wrapperClassControllerTEST {

    transient List<cContact> contactList {get; set;}

    public List<cContact> getContacts() {
        if(contactList == null) {
            contactList = new List<cContact>();
            for(Contact c: [select Id, Name, Email, Phone from Contact limit 10]) {
                contactList.add(new cContact(c));
            }
        }
        return contactList;
    }

     public PageReference save() {  
            List<Contact> Cs = new List<Contact>();
            for(cContact cCon: getContacts()) {
                 Cs.add(cCon.con);
            }          
            update Cs;
            contactList = null;
            getContacts();
            return null;     
        }

    public PageReference processSelected() {
        List<Contact> selectedContacts = new List<Contact>();
        for(cContact cCon: getContacts()) {
            if(cCon.selected == true) {
                selectedContacts.add(cCon.con);
            }
        }
        System.debug('These are the selected Contacts...');
        for(Contact con: selectedContacts) {
            system.debug(con);
        }
        contactList=null; // we need this line if we performed a write operation  because getContacts gets a fresh list now
        return null;
    }

    // This is our wrapper/container class. A container class is a class, a data structure, or an abstract data type whose instances are collections of other objects. In this example a wrapper class contains both the standard salesforce object Contact and a Boolean value
    public class cContact {
       public Contact con {get; set;}
       public Boolean selected {get; set;}
        public cContact(Contact c) {
            con = c;
            selected = false;
        }
    }
}



justinhowell82justinhowell82
page:

<apex:page controller="wrapperClassControllerTEST">
    <apex:form >
        <apex:pageBlock >
            <apex:pageBlockButtons >
                <apex:commandButton value="Process Selected" action="{!processSelected}" rerender="table"/>             
                <apex:commandButton value="save" action="{!save}" rerender="table"/>
            </apex:pageBlockButtons>
            <!-- In our table we are displaying the cContact records -->
            <apex:pageBlockTable value="{!contacts}" var="c" id="table">
                <apex:column >
                    <!-- This is our selected Boolean property in our wrapper class -->
                    <apex:inputCheckbox value="{!c.selected}"/>
                </apex:column>
                <!-- This is how we access the contact values within our cContact container/wrapper -->
               
                <apex:column >
                    <apex:inputField value="{!c.con.Name}" />
                </apex:column>
               
                <apex:column >
                    <apex:inputField value="{!c.con.Email}" />
                </apex:column>
                
                 <apex:column >
                    <apex:inputField value="{!c.con.Phone}" />
                </apex:column>
            </apex:pageBlockTable>
        </apex:pageBlock>
    </apex:form>
</apex:page>
justinhowell82justinhowell82
controller and page are in the above comments.  The save method is what I am working with.  It seems to save fine with the contactList defined as transient and it is not saved to the viewstate.  If you look at viewstate with it define as transient and cpompare when defined as public it is definately smaller.

Thanks,
Justin
KeerthigeeKeerthigee
Hi,

I think , this link  will be helpful.

https://developer.salesforce.com/page/An_Introduction_to_Visualforce_View_State.

Thanks.
justinhowell82justinhowell82
Thanks for the link, I have viewed that in the past.  I does not solve my confusion though.  I am sure I am just thinking about it incorrectly but I was hoping for an explanation with the code posted above.

Thanks,
Justin