Monday 4 October 2010

Creating a picklist in a Visualforce page without a -none- value

Update (7th August 2012): I have developed a new Visualforce component version of this functionality, for those who want to re-use this feature numerous times.

When building a custom Visualforce page, the need may arise to include a combo-box input based on a picklist field inside a Salesforce object. This is easy to achieve using an apex:inputField, as in the following example, where an Invoice Statement object contains a picklist field called Status.

VisualForce Page:
<apex:page controller="NoNoneForPicklistController">

    Please select required status:
    <apex:form >
        <apex:inputField value="{!invoiceStatement.Status__c}"/>
    </apex:form>  

</apex:page>
Controller:
public class NoNoneForPicklistController{

    public Invoice_Statement__c invoiceStatement {get;set;}
    
}

Screen-shot:


As you can see, the default value on the combo-box on the page is "-None-", which represents an empty value. It may be a preference to not display the empty value, but rather frustratingly, no configuration of the picklist object field can avoid this inclusion. There is no way to mark a picklist field as "required", and setting an option as default makes no difference either. That said, there are already ways to prevent an empty value being processed, using validation and feedback, but I have always been one to believe that prevention is better than cure.

Thankfully, there is a way to effectively create a picklist on a Visualforce list with no empty value. This can be achieved by using the Schema.DescribeFieldResult Salesforce standard class to retrieve all the possible field label value pairs for a picklist field. The retrieved value pairs are then stored inside a collection of select option objects, which can be used as the basis of a select list. Below is a snapshot of the code from the apex controller, and also the Visualforce page. As an added bonus, the default value specified in the picklist field object configuration can be used to set the initially selected value of the select list.

VisualForce Page:
<apex:page controller="NoNoneForPicklistController">

    Please select required status:
    <apex:form >
        <apex:selectList size="1" value="{!invoiceStatement.Status__c}">
            <apex:selectOptions value="{!statusOptions}"/>
        </apex:selectList>
    </apex:form>  

</apex:page>

Controller:
public class NoNoneForPicklistController{

    public Invoice_Statement__c invoiceStatement {get;set;}
    public List<SelectOption> statusOptions {get;set;}
    
    // Constructor called when page is accessed.
    public NoNoneForPicklistController() {
    
        invoiceStatement = new Invoice_Statement__c();        
        statusOptions = new List<SelectOption>();

        // Use DescribeFieldResult object to retrieve status field.
        Schema.DescribeFieldResult statusFieldDescription =                     Invoice_Statement__c.Status__c.getDescribe();

        // For each picklist value, create a new select option
        for (Schema.Picklistentry picklistEntry:                                statusFieldDescription.getPicklistValues()){

            statusOptions.add(new SelectOption(                                     pickListEntry.getValue(),pickListEntry.getLabel()));

            // obtain and assign default value
            if (picklistEntry.defaultValue){
                invoiceStatement.Status__c = pickListEntry.getValue();
            }  
        }     
    }
}

Screen-shot: