+ Start a Discussion
michaelforcemichaelforce 

dynamicComponent get method running wild

Hey folks, I've been playing with Dynamic Visualforce pretty heavily lately.  I noticed something funny and wanted to see if it is "normal" / expected behavior or not.  The deal is, when you have a dynamicComponent on the page and you reRender another part of the page (a section that doesn't contain the dynamicComponent) the get method for the dynamicComponent is still running again.

 

Below is an elementary example.  We have a dynamicComponent whose get method will return an empty PageBlock and has a debug statement to make it clear when that get method runs.  Then below that is a section with a button inside it that will reRender when the button is pushed without reloading the page (i.e. return type is void, not PageReference).

 

When you click the button and check the debug log for that button push, you will see that the "getTheBlock" method ran even though the dynamicComponent wasn't "supposed" to be reRendered.  Puzzling!

 

Page:

 

<apex:page controller="troubleController">
    <apex:form >

        <apex:dynamicComponent componentValue="{!theBlock}"/>
    
        <apex:outputPanel id="mySection">
            <apex:commandButton value="reRender below value" action="{!someAction}" reRender="mySection"/>
            <br/>{!now()}
        </apex:outputPanel>

    </apex:form>
</apex:page>

 Controller:

public with sharing class troubleController {

    public void someAction(){}

    public Component.Apex.PageBlock getTheBlock() {
    
        system.debug('The block is being got!');
    
        Component.Apex.PageBlock block = new Component.Apex.PageBlock();
        return block;
    }
}

 

aballardaballard

get methods are in general going to be called on postback requests, whether or not a given component is rendered.  This is part of restoring the original state needed to correctly interpret the posted data. 

 

 

michaelforcemichaelforce

That may end up being the answer with respect to get methods for dynamicComponents, but if you do the same experiment for a simpler element the get method doesn't run.  For example, I tried displaying some text using a get method, and the method only runs when the page loads or the text is reRendered.

aballardaballard

Not entirely.  It depends where you reference it.  For example if you have a getter referenced in a rendered attribute it WILL be called on the postback. 

 

The bottom line is you should not make assumptions about when or if a getter will be called. 

 

(That said, I see that for the dynamic component the call is happenning AFTER the action is invoked so it is not for the purpose I described.  Possibly some processing there could be trimmed....)

 

joshbirkjoshbirk

Yeah, I see the same results with a similar use case - and it seems the getter is getting called even if the component is set with a rendered of false.  Could not tell you if that's by design to allow for some kind of component processing across use cases, or just a matter of how Visualforce is walking through the tree of things it needs to to do in order to parse/process.  Kind of exaggerated by the specific ways in which Dynamic VF likes to access getters, too.

 

A bit blunt force, but wrapping the code would obviously catch the scenario.  A la:

 

public Component.Apex.OutputText getOutText() {
        if(isNow == null) {
            Component.Apex.OutputText outText = new Component.Apex.OutputText();
            outText.value = 'Hello World:'+String.valueOf(DateTime.Now());
            isNow = String.valueOf(DateTime.Now());
            return outText;
        }
        return null;
    } 

 

 

However - obviously if you DO rerender that component ... you'll be returning a null when you want your component.  So you'd have to reset your control var.  Like:

 

public void someAction(){isNow = null;}

 In this example.