A question was posted in that blog entry that asked if it was possible to have two picklists for different fields on the same Visualforce page. I replied with an answer that was basically "write the code out twice". While this works, its not exactly re-usable or easy to maintain.
Being a big fan of Visualforce components, I set about converting the no '-none-' picklist code into a re-usable component that can be placed onto any number of pages, and used in different applications easily. I found that this was possible by using the describe object and describe field calls.
The component I have created is called InputPicklistNoNone. It has two attribute arguments that have to be defined when using it in a Visualforce Page:
- Value: This is the reference for the variable you want to assign the picklist selection to. It is much like the value attribute for most Visaulforce input components, such as apex:inputField and apex:inputText.
- Field: This is the API reference of the picklist field you want to extract the possible values from. If this value points to an invalid field, an error message will be added to the page.
Component Code:
<apex:component controller="InputPicklistNoNoneController"> <apex:attribute name="value" required="true" type="String" description="The variable the selected option will be assigned to"/> <apex:attribute name="field" assignTo="{!fieldName}" required="true" type="String" description="The picklist field that forms the basis of the input"/> <!--If the value is empty, then set it to be equal to the default value from the schema description--> <apex:variable var="value" value="{!defaultOption}" rendered="{!ISNULL(value)}"/> <apex:selectList size="1" value="{!value}"> <apex:selectOptions value="{!options}"/> </apex:selectList> </apex:component>
Component Controller:
public class InputPicklistNoNoneController { public String defaultOption {get;set;} public List<SelectOption> options {get;set;} public String fieldName { get; set { fieldName = value; options = new List<SelectOption>(); List<String> fieldNameSplit = fieldName.split('\\.'); Schema.DescribeFieldResult picklistFieldDescription = Schema.getGlobalDescribe().get(fieldNameSplit[0]) .getDescribe().fields.getMap() .get(fieldNameSplit[1]).getDescribe(); for (Schema.Picklistentry picklistEntry: picklistFieldDescription.getPicklistValues()) { options.add(new SelectOption(pickListEntry.getValue(), pickListEntry.getLabel())); if (picklistEntry.defaultValue) { defaultOption = pickListEntry.getValue(); } } } } }
Example Page:
<apex:page standardController="Invoice_Statement__c" extensions="InputPicklistNoNoneExampleExtension"> <apex:sectionHeader title="No none picklist component example"/> <apex:form > <apex:panelGrid columns="2"> <!-- The component can be used to populate an object field --> <apex:outputText value="Status:"/> <c:InputPicklistNoNone value="{!Invoice_Statement__c.Status__c}" field="Invoice_Statement__c.Status__c"/> <!-- The component can also be used with a controller variable --> <apex:outputText value="Industry:"/> <c:InputPicklistNoNone value="{!myControllerVariable}" field="Account.Industry"/> <apex:commandButton value="Save" action="{!save}"/> </apex:panelGrid> </apex:form> </apex:page>
Example Controller Extension:
public class InputPicklistNoNoneExampleExtension { public String myControllerVariable {get; set;} public InputPicklistNoNoneExampleExtension( ApexPages.StandardController controller) {} }
Screenshot of Example Page:
I am a big fan of how this has turned out, it keeps the functionality intact while making it easily adaptable for use on numerous variables on any number of pages, result! If you have any questions, or need some pointers on how to use it, then please add a comment below.