1

On my account detail VF page, I have added 5 custom related lists. 3 of those related lists have <apex:actionfunction> in the component code. I found out that the constructors of these components are getting called twice. The constructors of the other 2 related lists are not getting called twice. I researched and found two useful links: link 1 & link 2.

The solution would be to use init function:

<apex:page action="{!init}" controller="sampleController">
...
</apex:page>

But in my case, the constructors are being called from <apex:component> and not <apex:page>. How do I use init function for <apex:component>? Please guide. Thank You!

Updates:

The constructors of the components are called twice and not the page.

Example of how the classes are called from components:

<apex:component controller="RelatedListDisplayController" allowDML="true">
     <apex:actionFunction action="{!DeleteAddress}" name="DeleteAddress" reRender="relcad" oncomplete="window.location.reload(false);"> 
    </apex:actionFunction> 
</apex:component>

3
  • 4
    I think I'm missing some of the relevant code here. You're using a Visualforce page with several Visualforce components inside of it, and they all share the same controller (therefore, the same constructor)?
    – nbrown
    May 29, 2020 at 14:25
  • @nbrown Each component (custom related list) has it's own controller. Those are the ones getting called twice. I have updated the question. Please check.
    – Koustubh
    Jun 1, 2020 at 14:31
  • This is tough. The constructors being called more than once should not have any side effects. If the constructors do have side effects, I would consider changing the component controllers so that getters and setters are doing more of the initialization than the constructor. : Examples of Visualforce Page Execution Order & Order of Execution for Visualforce Page Get Requests
    – nbrown
    Jun 1, 2020 at 15:06

1 Answer 1

2
+50

This has been a long time known bug. Just the mere presence of actionFunction will trigger the constructor twice in visualforce component controller.

Another big problem with visualforce controller is, the constructor is called is invoked even before the values are assigned. So, you cannot refer the values of the attributes in constructor.

Solution:

You should invoke the initMethod in the attribute assignment instead of constructor/actionFunction. Beware that even this may be assigned/set more than once and so you should use a boolean. Below is sample controller of component:

public class pocAccountController {
    
    Boolean init = false;
    
    public String myString{
        get {
            return myString;
        }
        set {
            if(!init) {
                System.debug('myString =>'+value);
                myString = value;
                initMethod();
                init = true;
            }
        }
    }
    
    public pocAccountController() {
        System.debug('constructor');
    }
    
    public void initMethod() {
        System.debug('initMethod');
    }
    
}

and its component:

<apex:component controller="pocAccountController" >
    <apex:attribute name="myStr" assignTo="{!myString}" type="String" required="true" description="string"/>

    <apex:form>
        poc Comp
    </apex:form>
</apex:component>

and sample page:

<apex:page >
    
    <c:pocComp myStr="my Sample string" />
        
</apex:page>

Ofcourse this way of implementation is not at all ideal but these are the work-arounds for the bugs we have for visualforce. Any logic which needs assigned values should be in initMethod and constructor logic should not depend on assigned values. Atleast the above work-around will make sure that the integrity of flow is maintained.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .