+ Start a Discussion
Denise CrosbyDenise Crosby 

visualforce page with 4000+ lines of code - split into components?

Hello friends,
I inherited a visualforce page with over 4000 lines of code in it. It is hitting the 'Maximum view state size limit (135KB) exceeded' error message. I know that queries in the custom controller need to be obtimized, etc, but there are 56 select statements and I'm not familiar with the data structure at all. Is there a fairly simple, fast way to break the page into components similar to how we break pages into components in Lightning? And should I expect that will help the performance? Tech lead has suggested that I split it into 2 visualforce pages, to quickly get past this problem. The first page would have a single apex:selectlist that the user must select from. The second page would have everything else with data dependent upon the selection from the apex:selectlist on the first page. I'm not convinced this will solve the problem though. We plan to move to Lightning soon, so we don't want to completely rebuild in visualforce. Any advice here is greatly appreciated.

Sample code is posted here. There are a total of 112 output panels on this page and it looks like some of them are rendered or not based on boolean values. Ugh.
<!--Salesforce Licenses-->
             <div class="row">
                <div class="col-sm-12 m40">  
                    <a name="bac"></a>
                    <apex:outputPanel id="SalesforceLicensesRepeat">
                    <table cellpadding="0" cellspacing="0" class="bordered" style="width:1280px;border:1px solid #222;">
                    <tr>
                        <td colspan="9" class="darkgrayback">
                            <div class="tabletop noborder">
                                Salesforce Licenses
                            </div>
                        </td>
                    </tr>
                    <tr>
                        <td class="lightgreenback borderbottom1 thead"></td>
                        <td class="lightgreenback borderbottom1 thead">Value</td>
                        <td class="lightgreenback borderbottom1 thead">Description</td>
                        <td class="lightgreenback borderbottom1 thead">Notes</td>
                        <td class="lightgreenback borderbottom1 thead">Attachment</td>
                        <td class="lightgreenback borderbottom1 thead">Confirmation</td>
                        <td class="lightgreenback borderbottom1 thead">Date</td>
                        <td class="lightgreenback borderbottom1 thead">Fund Code</td>
                        <td class="lightgreenback borderbottom1 thead"></td>
                    </tr>  
                    <apex:repeat value="{!SalesforceLicenses}" var="ba">   
                    <tr>
                        <td class="lightgreenback" style="text-align:center;"><apex:commandLink action="{!EditBudgetItem}" oncomplete="showModal('BItemModal')" rerender="binewpanel">
                                <apex:param name="editid" value="{!ba.Id}" assignTo="{!editid}"/>Edit</apex:commandLink>
                        </td>
                        <td class="lightgreenback"><apex:outputField value="{!ba.Value__c}" /></td>
                        <td class="lightgreenback"><apex:outputField value="{!ba.Description__c}" /></td>
                        <td class="lightgreenback"><apex:outputField value="{!ba.Notes__c}" /></td>
                        <td class="lightgreenback" style="text-align:center;">
                            <apex:repeat value="{!ba.Attachments}" var="att">
                                <a href="/servlet/servlet.FileDownload?file={!att.Id}" target="_blank" style="color:#000;text-decoration:underline;">View/Download Attachment</a><br />
                            </apex:repeat>
                            <apex:outputPanel rendered="{!ba.Attachments.size == 0}">
                                    <a href="#AttachModal" data-toggle="modal" data-target="#AttachModal" onclick="UpRecordId('{!ba.Id}')">+ Add</a>
                            </apex:outputPanel>                            
                        </td>
                        <td class="lightgreenback"><apex:outputField value="{!ba.Confirmation__c}" /></td>
                        <td class="lightgreenback"><apex:outputField value="{!ba.Date__c}" /></td>
                        <td class="lightgreenback"><apex:outputField value="{!ba.Fund_Code__c}" /></td>
                        <td class="lightgreenback" style="text-align:center;">
                            <apex:commandLink action="{!DeleteBudgetItem}" onclick="if(!confirm('Are you sure you want to delete this item?\n\nThis action cannot be undone.')){return false};"  rerender="CMOPanel">
                                <apex:param name="delid" value="{!ba.Id}" assignTo="{!delid}"/>Delete</apex:commandLink>
                        </td>
                    </tr>  
                    </apex:repeat> 
                        
                    <tr>
                        <td class="lightgreenback totborder">Total</td>
                        <td class="lightgreenback totborder">
                            <apex:outputText value="${0, number,###,###,###,###}"> 
                                <apex:param value="{!TotalSalesforceLicenses}"/> 
                            </apex:outputText>
                        </td>
                        <td class="lightgreenback totborder"></td>
                        <td class="lightgreenback totborder"></td>
                        <td class="lightgreenback totborder"></td>
                        <td class="lightgreenback totborder"></td>
                        <td class="lightgreenback totborder"></td>
                        <td class="lightgreenback totborder"></td>
                        <td class="lightgreenback totborder"></td>
                    </tr>  

                        
                    <tr>
                        <td colspan="9" class="noback">                         
                            <div style="text-align:right;">
                                <apex:commandLink action="{!NewBudgetItem}" oncomplete="showModal('BItemModal')" rerender="binewpanel" styleClass="btn btn-primary bimodal">
                                <apex:param name="editid" value="Salesforce Licenses" assignTo="{!editid}"/>+ Add</apex:commandLink>
                            </div>                            
                        </td>
                    </tr>
                    
                    
                    </table>
                    </apex:outputPanel>
                </div>
            </div>

 
Best Answer chosen by Denise Crosby
Alain CabonAlain Cabon
Hi Denise,

You are looking for quick refactoring techniques for VFP without any recoding as far as possible.

Salesforce always quotes the transient keyword but static is also interesting.

A much more complicated technique to implement is to put more accesses to your data in the client side with Visualforce Remoting in javascript (... recoding needed so expensive, not to say very expensive).

7 Habits of Highly Efficient Visualforce Pages:
https://www.slideshare.net/developerforce/df121306-ready
User-added image
User-added image

sfdcfox is interesting (as usual) in this thread:
https://salesforce.stackexchange.com/questions/190970/when-to-use-static-variables-in-apex-controller

 

All Answers

Alain CabonAlain Cabon
Hi Denise,

You are looking for quick refactoring techniques for VFP without any recoding as far as possible.

Salesforce always quotes the transient keyword but static is also interesting.

A much more complicated technique to implement is to put more accesses to your data in the client side with Visualforce Remoting in javascript (... recoding needed so expensive, not to say very expensive).

7 Habits of Highly Efficient Visualforce Pages:
https://www.slideshare.net/developerforce/df121306-ready
User-added image
User-added image

sfdcfox is interesting (as usual) in this thread:
https://salesforce.stackexchange.com/questions/190970/when-to-use-static-variables-in-apex-controller

 
This was selected as the best answer
Denise CrosbyDenise Crosby
Thank you so much Alain. Yeah, I guess transient may be the first thing to try. If the page runs 56 SOQL queries, surely all that data can't be expected to remain in view state. I'll give it a try and report back. :) Thanks!
Alain CabonAlain Cabon
Hi Denise,

There are not many alternatives posted here even if your problem is interesting but the documentation is limited to a few examples.

The sfdcfox's explanation above remains the most interesting (concise with short codes).

You could be more successful on https://salesforce.stackexchange.com  with the same question perhaps.

Let us know if you have some progress with these techniques (split of the page, use of the transient keyword + getter/setter, and so on, technique boundaries as well for your huge VFP perhaps).
 
Denise CrosbyDenise Crosby
Thanks Alain,
I did use the transient keyword on some of the ArrayLists on the page and it did reduce the view state. It appears from your examples that static would give the same result. I think for right now, I am ok. If I have more time later, I'll look into this in more detail.
Thanks so much for helping!
Denise