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
Frank N.Frank N. 

Custom Components, AJAX & Viewstate horror !! Bug in Force.com?

Hi all,

 

This is related to my previous post:Actionregions

 

I wonder if this is a bug in Salesforce and how to solve this. Apparantly custom components on the page always become part of the viewstate, even if they are NOT part of any form tag. This means that when I perform an AJAX request using actionFunction's, it returns an AJAX result but at the same time If I look in my debug logs, I see its also calling all functions from the custom components that are used to, for example build navigation as well as the login bar.

 

This does not seem correct and looks like a bug from Force.com. My first solution was to add one form tag in the Master template and use actionRegion's in the custom components to differentiate the different postbacks. However, this broke the custom components and they stopped working completely.

 

My second solution, which works, is to declare all variables used by the components Transient so they are not put in the viewstate. Then, I have a Transient Boolean called isAjaxPostback and in the function where the navigation is rebuilt, I check if isAjaxPostback equals null, then do not call the function. Now, on AJAX postbacks, it still calls the function in the components, but it doesnt run so I am happy with that.

 

Is this the correct way of solving my issue? If not and this is common, how do I proceed as its impact on speed and viewstate is enormous.

 

Best,

Frank

joshbirkjoshbirk

"Apparantly custom components on the page always become part of the viewstate, even if they are NOT part of any form tag."

 

I'm not sure what you mean by this without looking at the code.  If the components need to send data back to the controller, they would need to be embedded in a form tag and would then become part of the viewstate.

 

However, the short version may just be that:

 

"My second solution, which works, is to declare all variables used by the components Transient so they are not put in the viewstate. Then, I have a Transient Boolean called isAjaxPostback and in the function where the navigation is rebuilt, I check if isAjaxPostback equals null, then do not call the function. Now, on AJAX postbacks, it still calls the function in the components, but it doesnt run so I am happy with that."

 

Seems like a perfectly elegant solution to me.  Transient is your friend.

Frank N.Frank N.

Hi Josh,

 

It would be an elegant solution if it were really the case. Example: We have a navigation bar that calls a specific function rebuild a hierarchy of products. There is NO form tag in this component nor is there one surrounding it in the master template.

 

This is how it is included:

 

<apex:define name="ProductNavigation">
    <c:Collaborate_ProductNavigation key="ProductNavigation" pageController="{!this}" />
</apex:define>

 Inside the product navigation there is no form tag. Still, on any AJAX request the function that rebuilds the navigation inside the custom component gets called:

 

 /*
    * Method name   : productHierarchy
    * @description  : Returns product hierarchy based on user outlets' portfolios
    * @return       : List<Collaborate_UserProductHierarchy.ProductHierarchy>
    */
    public List<Collaborate_UserProductHierarchy.ProductHierarchy> productHierarchy {
        public get{
        	 if(isAjaxPostback==null)
        		return null;
        		
        	return objCollaborate_UserProductHierarchy.productHierarchy;
        }
       
    }

 As you can see, I added the isAjaxPostback to check if it is a postback, if it i,s it doesnt rebuild the menu.

 

Question 1: Might this something have to do with the fact it's a custom get, set variable?

 

Question 2: How can I use actionRegions inside custom components for those custom components where I do use form variables? Apparantly if I do that it doesnt work (postbacks fail, JS fails).

 

Thanks!

 

Frank N.Frank N.

Just some more info in a previous post: Similar issue, more info

 

Iam starting to think its an innate bug of Salesforce.

joshbirkjoshbirk

So if you haven't seen it, I'd recommend checking out this from DF11: http://blogs.developerforce.com/developer-relations/2011/10/df11-recap-blazing-fast-visualforce.html

 

Particularly the video itself, Stephan goes through a lot of explanation as to what goes into the viewstate and why.  Related components could get pulled in if the controller thinks that is something which may need to be re-rendered for any reason. It also does a better job of walking through the viewstate inspector than I could do in words.

 

Transient is probably one of the better tools out there to control this - so is there is something currently wrong/annoying about your current solution?

 

Might this something have to do with the fact it's a custom get, set variable?

I don't think so, it's just a matter of whether the controller thinks those variables might be related

 

How can I use actionRegions inside custom components for those custom components where I do use form variables? Apparantly if I do that it doesnt work (postbacks fail, JS fails).

So, remember that actionRegion just limits the information being sent back to the controller - not the rerendering behavior.  It aids in performance if you have a large form because not all of that information needs to go back necessarily and it can fix situations where you have component ABC and D, and you if you submit A and B your processing for C will fail (for instance, you want logic on a field of a bound record - but not the whole record).  But it won't affect your overall viewstate.

 

You might try adding an outputPanel to portions of the page you know should get rerender, outside your navigation components, and then make sure your rerenders are all pointing to that.

Frank N.Frank N.

Good stuff thanks! Guess its not a bad solution after all. I'll have a look today, I think reducing our viewstate is the next way to go!

 

 

Frank N.Frank N.

We have solved this issue accordingly and made portal much faster. Furthermore we've setup a blog where we discuss our issues and solutions:

 

Three heads on a pike - Salesforce BLOG

 

Solution can be found at:

Solution

Mitesh SuraMitesh Sura
Although this is old thread, this link may help http://salesforce.stackexchange.com/questions/4537/how-to-reduce-a-large-internal-view-state-what-is-in-the-internal-view-state 

ViewState can be confusing esp with little documentation. Your controller and custom component may be good, but it may be related to complex nesting or using repeat tags along with apex:input and apex:output tags. Again, that link explains in detail. 

Hope it helps someone. 

Mitesh