Apex:SelectOption does not show selected value on page reload

apexselectoptionvisualforce

I am trying to get values for apex select list from a API call.
I can get all the values, show them on the page, do what I need to do etc.
However, when I reload the page, I my dropdown list does not retain the selected value.

VF Page code

<apex:page standardController="Signature__c" extensions="DocusignTemplates" lightningStylesheets="true">
    <apex:form style="margin-left:-0.9em">
        <apex:outputLabel >Select Template</apex:outputLabel><br/>
        <apex:selectList size="1" style="margin-left:0px;width:100%" value="{!selectedTemplate}">
            <apex:actionSupport event="onchange" action="{!updateSelectedTemplate}"/>
            <apex:selectOptions value="{!filteredTemplates}"/>
        </apex:selectList><p/>
    </apex:form>
</apex:page>

Controller Class

public class DocusignTemplates {
    private Signature__c signatures;
    public String selectedTemplate;
    public DocusignTemplates (ApexPages.StandardController controller) {
        signatures = (Signature__c)controller.getRecord();
    }
    
    public DocusignRESTUtility dru = new DocuSignRESTUtility();
    public String templatesJSON = dru.getDocusignData(DocuSignRESTUtility.TEMPLATES);
    public DocusignTemplateListBean templateData = (DocusignTemplateListBean) System.JSON.deserialize(templatesJSON, DocusignTemplateListBean.class);
    public List <EnvelopeTemplateBean> envelopeTemplates = templateData.envelopeTemplates;
    
    public List <SelectOption> getFilteredTemplates() {
        List <SelectOption> myTemplates = new List<SelectOption>();
        myTemplates.add(new SelectOption('','--No Template--'));
        for(EnvelopeTemplateBean envelopeTemplate : envelopeTemplates) {
                if(envelopeTemplate.name != '')
                    myTemplates.add(new SelectOption(envelopeTemplate.templateId, envelopeTemplate.name));
        }
        return myTemplates;
    }
    
    public String getSelectedTemplate() {
        return selectedTemplate;
    }
    public void setSelectedTemplate(String templateId) {
        this.selectedTemplate = templateId;
    }
    
    public PageReference updateSelectedTemplate() {
        system.debug('selected template: '+ getSelectedTemplate());
        this.signatures.Selected_Template__c = getSelectedTemplate();
        update this.signatures;
        return null;
    }
}

Before reloading page, everything works fine and I can store value in another field

Before reloading page

After reloading page, selected value is not restored from another field
enter image description here

How do I retain the value in Dropdown after page reload?

Best Answer

When you say "relaod page" I'm assuming you mean when the page refreshes due to action method updateSelectedTemplate (the return null). Normally, one simply makes the action method void if you are not causing a new Page to be displayed (wizard-style or redirect)

I would suggest you make the selectOptions a lazyload and move the docusign call into the lazyload rather than when the controller is instantiated. This helps avoid the indeterminate ordering of getters

public List <SelectOption> filteredTemplates {
    get {
      if (filteredTemplates == null) {
         DocusignRESTUtility dru = new DocuSignRESTUtility();
         String templatesJSON = 
            dru.getDocusignData(DocuSignRESTUtility.TEMPLATES);
         DocusignTemplateListBean templateData = (DocusignTemplateListBean) System.JSON.deserialize(templatesJSON, DocusignTemplateListBean.class);

         filteredTemplates = new List<SelectOption>();
         filteredTemplates.add(new SelectOption('','--No Template--'));
         for(EnvelopeTemplateBean envelopeTemplate : envelopeTemplates) {
            if(envelopeTemplate.name != '')
                filteredTemplates.add(new SelectOption(envelopeTemplate.templateId, envelopeTemplate.name));
       }
       return filteredTemplates;
    } private set;
}

I would also make for convention (only variables that the VF page references directly should be public:

private String selectedTemplate;

and for clarity and consistency

public String getSelectedTemplate() {
    return this.selectedTemplate;
}