1

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. There are a couple of examples for this, but I could not get it to work.

I have an actionSupport element on the picklist that calls the method updateUnlockfieldsVisibility() in the extension that evaluates the picklist value and sets a flag (unlockFieldsVisibility) that decides if the additional input fields are rendered.

My problem is that the variable that contains the picklist value (newInstruction) is always null. When the command button is clicked, is has a value and the form works fine. But when the action is called, it is null. Why is it not set to the value selected in the picklist?

Here is my Visualforce page:

<apex:page standardController="CaseCard__c" extensions="CardExtension" recordSetVar="caseCards">
    <apex:form >
        <apex:pageMessages />
        <apex:pageBlock title="Select the instruction for these cards">
            <apex:pageBlockButtons >
                <apex:commandButton action="{!setInstruction}" value="Set Instructions"/>
            </apex:pageBlockButtons>
            <apex:pageBlockSection id="inputSection">
                <apex:actionRegion>
                    <table style="width:100%">
                        <tr>
                            <td>New instruction:</td>
                            <td><apex:selectList value="{!newInstruction}" multiselect="false" size="1">
                                    <apex:selectOptions value="{!instructions}"/>
                                    <apex:actionSupport event="onchange" action="{!updateUnlockfieldsVisibility}" reRender="inputSection" immediate="TRUE"/>
                                </apex:selectList>
                            </td> 
                        </tr>
                        <apex:pageBlockSection id="unlockFields" rendered="{!unlockFieldsVisibility}">
                        <tr>
                            <td>Unlock reason:</td>
                            <td><apex:selectList value="{!newUnlockReason}" multiselect="false" size="1">
                                <apex:selectOptions value="{!unlockReasons}" />
                                </apex:selectList>
                            </td> 
                        </tr>
                        <tr>
                            <td>Unlock comment:</td>
                            <td><apex:inputTextarea value="{!newUnlockComment}" id="unlockComment"/></td> 
                        </tr>
                        </apex:pageBlockSection>
                    </table>
                </apex:actionRegion>
            </apex:pageBlockSection>
        </apex:pageBlock>
    </apex:form>
</apex:page>

And here is part of 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 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
##### NullPointerException on next line; newInstruction is null #####
        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 setInstruction() {
        //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();
    }
}
3
  • Without a submit action that value isn't going to your controller. Have you tried an apex:param? Commented Feb 5, 2016 at 14:14
  • I thought that reRender communicates with the controller via Ajax and that all variables within the section that is rerendered would be transmitted. How would I add a submit action? I added apex:param as a child to apex:actionSupport (<apex:param name="inst" value="{!newInstruction}"/>), parsed the parameter in the controller (String inst = ApexPages.currentPage().getParameters().get('inst');), but it is an empty string.
    – georg w.
    Commented Feb 5, 2016 at 14:26
  • Try removing the ``immediate="TRUE"` from your <apex:actionsupport> command. Also, I think you may want that particular action to be an actionfunction and the actionregion to encompass what follows it.
    – crmprogdev
    Commented Feb 5, 2016 at 14:58

2 Answers 2

1

The specific reason for your error is the use of immediate="true"

Per the SFDC Doc on VF Page Order of Execution,

  1. During a postback request, the view state is decoded and used as the basis for updating the values on the page.

Note A component with the immediate attribute set to true bypasses this phase of the request. In other words, the action executes, but no validation is performed on the inputs and no data changes on the page.

  1. After the view state is decoded, expressions are evaluated and set methods on the controller and any controller extensions, including set methods in controllers defined for custom components, are executed.

Hence, the value of merge field {!instructions} is not sent to the controller on the onchange event.

You can also see more on this including a workaround using actionRegion in this SFSE answer

1
  • Thanks a lot, that solved the immediate problem of setting the variable in the controller. Thanks also to @crmprogdev who also pointed this out in his comment. I now have a different problem and opened this question: salesforce.stackexchange.com/questions/108477/…
    – georg w.
    Commented Feb 9, 2016 at 10:42
0

Page

<apex:form id="form">            
    <apex:selectList id="selected_list" value="{!temp}" size="1">
        <apex:selectOption itemvalue="None" itemLabel="--None--"/>
        <apex:selectOption itemvalue="a" itemLabel="a"/>
        <apex:selectOption itemvalue="b" itemLabel="b"/>
        <apex:actionSupport event="onchange" reRender="form" action="{!find}"/>
    </apex:selectList>
    <br/>
    //your fields or w/e
    The value based on select list value: {!temp1}            
</apex:form>

Controller

    public String temp {get; set;}
    public String temp1 {get; set;}

    public void find() {    
        if(temp == 'a') {
            temp1 = 'Welcome';
        } else if(temp == 'b') {
            temp1 = 'Thank you';
        }
    }  

You must log in to answer this question.

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