0

(I am building upon this question and the helpful answers there: Re-rendering section on picklist value change - picklist value is always null.)

Requirement: On a Visualforce page, I have a picklist (apex:selectOption). When a user selects certain values, additional input fields have to appear. Otherwise, they should be hidden.

Implementation: The additional fields are in a pageBlockSection and a Boolean variable in rendered controls it's visibility. The onchange action on the picklist calls an actionFunction actUpdateUnlockFieldsVisibility which calls the controller method updateUnlockFieldsVisibility() which updates the Boolean variable unlockFieldsVisibility. The actionFunction's reRender should refresh a PageBlockSection that contains the additional input fields.

Problem: The variable is updated correctly in the controller extension (I see this in the debug log), but it is not updated in the Visualforce page. Basically, reRender in the actionFunction does not do anything. (I also tried having the actionRegion only around the PageBlockSection, but this did not change the behavior.) Any hints?

The page:

<apex:page standardController="CaseCard__c" extensions="CardExtension" recordSetVar="caseCards">
    <apex:form>
        <apex:actionFunction action="{!updateUnlockFieldsVisibility}" name="actUpdateUnlockFieldsVisibility" reRender="unlockFields" focus="unlockReasonPicklist"/>
        <apex:pageMessages />
        <apex:pageBlock >
            <apex:pageBlockButtons >
                <apex:commandButton action="{!issueInstruction}" value="Set Instructions"/>
            </apex:pageBlockButtons>
                    <apex:actionRegion>
                        <apex:selectList value="{!newInstruction}" multiselect="false" size="1" onchange="actUpdateUnlockFieldsVisibility()">
                            <apex:selectOptions value="{!instructions}"/>
                        </apex:selectList>
                        <apex:outputText>unlockFieldsVisibility: {!unlockFieldsVisibility}</apex:outputText>
                        <br/>
                        <apex:outputText>newInstruction: {!newInstruction}</apex:outputText>
                        <apex:pageBlockSection id="unlockFields" rendered="{!unlockFieldsVisibility}">
                            <apex:selectList value="{!newUnlockReason}" multiselect="false" size="1" id="unlockReasonPicklist">
                                <apex:selectOptions value="{!unlockReasons}" />
                            </apex:selectList>
                            <apex:inputTextarea value="{!newUnlockComment}" id="unlockComment"/>
                        </apex:pageBlockSection>
                    </apex:actionRegion>
            <apex:pageBlockTable value="{!cards}" var="card">
                [...]
            </apex:pageBlockTable>
        </apex:pageBlock>
    </apex:form>
</apex:page>

The controller extension:

public with sharing class CardExtension {
    public String newInstruction { get; set; }
    public String newUnlockReason { get; set; }
    public String newUnlockComment { get; set; }
    public Boolean unlockFieldsVisibility { get; set; }

    private Case currentCase;
    private ApexPages.StandardSetController standardController;

    public CardExtension(ApexPages.StandardSetController standardController) {
        this.standardController = standardController;
        unlockFieldsVisibility = false;
    }

    public PageReference updateUnlockFieldsVisibility() {
        System.debug('>>>> newInstruction: ' + newInstruction);
        System.debug('>>>> unlockFieldsVisibility: ' + unlockFieldsVisibility);
        //if unlock, show unlock reason picklist + unlock comment
        if (newInstruction.containsIgnoreCase('unlock')) {
            unlockFieldsVisibility = true;
        } else {
            unlockFieldsVisibility = false;
        }
        System.debug('>>>> unlockFieldsVisibility: ' + unlockFieldsVisibility);
        return ApexPages.currentPage();
    }

    //sets the selected instruction on all cards
    public PageReference issueInstruction() {
        //get the instruction and check if it is empty
        if (String.isEmpty(newInstruction)) {
            ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.ERROR, 'The instruction is empty.'));
            return ApexPages.currentPage();
        }
        //business logic here
        return ApexPages.currentPage();  
    }
}
1
  • You can try to wrap region to rerender in outputPanel. I have met issues with rerender of apex:pageBlockSection before, and that was one of the solutions
    – kurunve
    Feb 9, 2016 at 10:53

5 Answers 5

0

The issue here is you are trying to rerender a section which was previously not rendered on the page. "Rerender" attributes only renders those sections or panels which were rendered on the page initially or before the ajax request.

So you would have to rerender the "Apex:pageBlock" or put your selectList inside an outputPanel like this:

<apex:pageBlockSection id="unlockFields" >
      <apex:outputPanel rendered="{!unlockFieldsVisibility}">
                            <apex:selectList value="{!newUnlockReason}" multiselect="false" size="1" id="unlockReasonPicklist">
                                <apex:selectOptions value="{!unlockReasons}" />
                            </apex:selectList>
                            <apex:inputTextarea value="{!newUnlockComment}" id="unlockComment"/>
       <apex:outputPanel>
 </apex:pageBlockSection>
4
  • Hi Nitin, thanks for the advice. Using an outputPanel and re-rendering it did not change the behaviour, though.
    – georg w.
    Feb 9, 2016 at 11:57
  • did you removed the rendered attribute from the pageBlockSection?
    – Nitin
    Feb 9, 2016 at 13:01
  • Yes. The page looks like this: <apex:pageBlockSection id="unlockFields" > <apex:outputPanel rendered="{!unlockFieldsVisibility}"> <tr> <td>Unlock reason:</td> <td><apex:selectList value="{!newUnlockReason}" multiselect="false" size="1" id="unlockReasonPicklist"> <apex:selectOptions value="{!unlockReasons}" /> </apex:selectList> </td> </tr>
    – georg w.
    Feb 9, 2016 at 13:11
  • I'll accept this answer as it definitely points out a bug. See my own answer for what worked in the end.
    – georg w.
    Feb 11, 2016 at 17:10
0

The quick thing you can do it. Put the unlockFields id to parent container `PageBlock' as:

 <apex:pageBlock id="unlockFields">
        <apex:pageBlockButtons >
            <apex:commandButton action="{!issueInstruction}" value="Set Instructions"/>
        </apex:pageBlockButtons>
                <apex:actionRegion>
        ......
 </<apex:pageBlock>
3
  • Thank you. I tried to re-render the pageBlock instead of the pageBlockSection, but it did not work.
    – georg w.
    Feb 9, 2016 at 11:57
  • @georgw. you should try by removing action:region from the page. It can be an issue.
    – Ashwani
    Feb 9, 2016 at 11:59
  • I removed it, and the behavior did not change. So it was unnecessary, but did not hurt either.
    – georg w.
    Feb 9, 2016 at 12:42
0

Wrap your pageblocksection inside an outputpanel. Set it as always rendering. Based on your logic from the action function, re render the new outputpanel.

<apex:actionFunction action="{!updateUnlockFieldsVisibility}" name="actUpdateUnlockFieldsVisibility" reRender="panelUnlockFields" focus="unlockReasonPicklist"/>

<!-- more codes -->

<apex:outputPanel id="panelUnlockFields">
    <apex:pageBlockSection id="unlockFields" rendered="{!unlockFieldsVisibility}">
        <apex:selectList value="{!newUnlockReason}" multiselect="false" size="1" id="unlockReasonPicklist">
            <apex:selectOptions value="{!unlockReasons}" />
        </apex:selectList>
        <apex:inputTextarea value="{!newUnlockComment}" id="unlockComment"/>
    </apex:pageBlockSection>
</apex:outputPanel>
0

With the help of a friend his minimal working template, I was able to build a version that works. The controller extension is basically the same. I did not find out what actually caused the page not to work in the first place.

Here is the working version of my page:

<apex:page standardController="CaseCard__c" extensions="CardExtension" recordSetVar="caseCards" tabStyle="Card__c">
    <apex:form >
        <apex:pageMessages />
        <apex:pageBlock >
            <apex:pageBlockButtons >
                <apex:commandButton action="{!issueInstruction}" value="Set Instructions"/>
            </apex:pageBlockButtons>
            <table>
                <tr>
                    <td style="width:100px">New instruction:</td>
                    <td>
                        <apex:selectList value="{!newInstruction}" multiselect="false" size="1">
                            <apex:selectOptions value="{!instructions}"/>
                            <apex:actionSupport event="onchange" rerender="unlockFields" action="{!updateUnlockFieldsVisibility}" focus="unlockReasonPicklist"/>
                        </apex:selectList>
                    </td>
                </tr>
            </table>
            <apex:outputPanel id="unlockFields">
                <apex:outputPanel rendered="{!unlockFieldsVisibility}">
                    <apex:selectList value="{!newUnlockReason}" multiselect="false" size="1" id="unlockReasonPicklist">
                        <apex:selectOptions value="{!unlockReasons}" />
                    </apex:selectList>
                    <apex:inputTextarea value="{!newUnlockComment}" id="unlockComment"/>
                </apex:outputPanel>
            </apex:outputPanel>
            <br/>
            <apex:pageBlockTable value="{!cards}" var="card">
[...]
            </apex:pageBlockTable>
        </apex:pageBlock>
    </apex:form>
</apex:page>

Instead of the inner apex:outputPanel (with the rendered parameter), an apex:pageBlockSection also works.

0

The problem with the code is that you are using one page block section (id and rendered attributes are set there). Basically you are trying to re-render something that not exists(because the first value of the Boolean variable is false).

In order to fix this issue, you need to use two output panels. First panel will be with the id, and the second one with the rerender attribute.

Here is the example:

<apex:outputPanel id="sectionToBeRerendered" >
    <apex:outputPanel rendered="{!rerenderBoolean}">
    <!-- code here -->
    </apex:outputPanel>
</apex:outputPanel>

You must log in to answer this question.

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