Tweet |
Initially I was using the describe capability for the StageName field, which
worked fine for a single record type. However, as soon as I introduced
multiple opportunity record types with different sales processes, I hit
problems - regardless of the sales process, the full set of picklist values
was returned each time, even if I navigated to the field via an opportunity
with the appropriate record type. Some googling and searching on the
Developerforce discussion boards seemed to confirm that there isn't a simple
way to achieve this.
Clearly the information about which stages are applicable to a record type is
available to the Salesforce UI, as the Stage picklist contains the values
specific to the record type. Even better, this is respected when using a
Visualforce input field. Therefore one way of getting at this
information for use in a Visualforce controller is to have the page supply it.
Utilizing a technique I've written about before in DML During Initialisation, I created a page that would send the picklist values back to the controller
the first time it was loaded, and then display the details thereafter.
The first time that the page is loaded the following outputpanel is rendered:
This contains a hidden form with an inputfield for the opportunity stage and an input text element that will be used to submit the stage options to the controller. The reload() function is installed as an onload handler, and this extracts the option text, concatenates it into a single string value, populates the input text with this string and then submits the form.
When the page is reloaded, the following outputpanel is rendered - this simply creates a pageblocktable to iterate through the available values:
The controller is shown below - the heavy lifting is done by the reload() method - this parses the string containing the picklist values and stores them in a list property. it also sets the loadonce property to false, to ensure that the page is reloaded once and once only:
Here are a couple of screenshots of the page doing its thing for opportunities with two different record types. The first with just a few of the stages:
and the second with most of them:
For the sake of completeness, the entire page is shown below:
And a special thanks to the blogger software error that meant I had to write this post twice! Always save at regular intervals.
The first time that the page is loaded the following outputpanel is rendered:
<apex:outputPanel rendered="{!loadonce}"> <apex:form id="frm"> <apex:actionFunction name="reloadWithStages" action="{!reload}"/> <div id="test1" style="width: 100%; height: 150px;"></div> <apex:outputPanel layout="block" id="vals" style="display:none"> <apex:inputField value="{!Opportunity.StageName}" required="false" id="stages"/> <apex:inputText value="{!valsText}" required="false" id="back"/> </apex:outputPanel> </apex:form> <script> function reload() { var ele=document.getElementById('{!$Component.frm.stages}'); var idx=0; var valText=''; for (idx=0; idx<ele.length; idx++) { valText+=ele.options[idx].text + ':'; } var backele=document.getElementById('{!$Component.frm.back}'); backele.value=valText; reloadWithStages(); } window.onload=reload(); </script> </apex:outputPanel>
This contains a hidden form with an inputfield for the opportunity stage and an input text element that will be used to submit the stage options to the controller. The reload() function is installed as an onload handler, and this extracts the option text, concatenates it into a single string value, populates the input text with this string and then submits the form.
When the page is reloaded, the following outputpanel is rendered - this simply creates a pageblocktable to iterate through the available values:
<apex:outputPanel rendered="{!NOT(loadonce)}"> <apex:pageBlock title="Status Values for record type {!Opportunity.RecordType.Name}"> <apex:pageBlockTable value="{!pickListVals}" var="plVal"> <apex:column headerValue="Stage"> <apex:outputText value="{!plVal}"/> </apex:column> </apex:pageBlockTable> </apex:pageBlock> </apex:outputPanel>
The controller is shown below - the heavy lifting is done by the reload() method - this parses the string containing the picklist values and stores them in a list property. it also sets the loadonce property to false, to ensure that the page is reloaded once and once only:
public with sharing class RecordTypePickListController { public List<String> pickListVals {get; set;} public String valsText {get; set;} public Boolean loadOnce {get; set;} private Opportunity opp; public RecordTypePickListController(ApexPages.StandardController std) { opp=(Opportunity) std.getRecord(); loadOnce=true; } public PageReference reload() { pickListVals=new List<String>(); Boolean skip=true; for (String val : valsText.split(':')) { if (skip) { skip=false; } else { pickListVals.add(val); } } loadOnce=false; return null; } }
Here are a couple of screenshots of the page doing its thing for opportunities with two different record types. The first with just a few of the stages:
and the second with most of them:
For the sake of completeness, the entire page is shown below:
<apex:page standardController="Opportunity" extensions="RecordTypePickListController"> <apex:outputPanel rendered="{!loadonce}"> <apex:form id="frm"> <apex:actionFunction name="reloadWithStages" action="{!reload}"/> <div id="test1" style="width: 100%; height: 150px;"></div> <apex:outputPanel layout="block" id="vals" style="display:none"> <apex:inputField value="{!Opportunity.StageName}" required="false" id="stages"/> <apex:inputText value="{!valsText}" required="false" id="back"/> </apex:outputPanel> </apex:form> <script> function reload() { var ele=document.getElementById('{!$Component.frm.stages}'); var idx=0; var valText=''; for (idx=0; idx<ele.length; idx++) { valText+=ele.options[idx].text + ':'; } var backele=document.getElementById('{!$Component.frm.back}'); backele.value=valText; reloadWithStages(); } window.onload=reload(); </script> </apex:outputPanel> <apex:outputPanel rendered="{!NOT(loadonce)}"> <apex:pageBlock title="Status Values for record type {!Opportunity.RecordType.Name}"> <apex:pageBlockTable value="{!pickListVals}" var="plVal"> <apex:column headerValue="Stage"> <apex:outputText value="{!plVal}"/> </apex:column> </apex:pageBlockTable> </apex:pageBlock> </apex:outputPanel> </apex:page>
And a special thanks to the blogger software error that meant I had to write this post twice! Always save at regular intervals.