Tuesday, October 7, 2008

A Picklist Component For Your Visualforce Pages

The last couple of months, numerous times in order to view picklist values in a form either for filter the views or creating custom data entry forms, I had to come up with ways to get around the limitations and somehow hook the inputField with the picklist to show what I needed.

Now, with the Salesforce Winter 09 improvements now it is much easier to tackle this issue.

In this article we will design an Apex component that gets the picklist name as attribute and renders the picklist values in form of a dropdown list.

This component will be really useful for non-multi-select picklists. I will post another article on multiselect picklists in near future.

Let's see how the Component will be added to the Page:

<c:picklist id="industryPicklist" value="{!accountIndustry}" picklistField="Industry" systemEntity="Account" usedefaultvalue="true"/>

What you need to define for the component is what object, which picklist field of that Object and a property of your page's Controller allowing you to read what user's choice was.

Now let's dive into the code and see how this component is developed. Like most other Visualforce page developments our component has two parts. The User Interface elements and the controller behind it.


<apex:component controller="picklistController">
<apex:attribute name="SystemEntity" description="" type="String" required="true" default="Account" assignTo="{!systemObject}"></apex:attribute>
<apex:attribute name="picklistField" description="" type="String" required="true" default="Type" assignTo="{!picklist_Field}"></apex:attribute>
<apex:attribute name="value" description="" type="String" required="true"></apex:attribute>
<apex:attribute name="defaultLabel" description="default value to be shown to user" type="String" assignTo="{!listDefaultLabel}" default="--None--"></apex:attribute>
<apex:attribute name="defaultValue" description="default value to be shown to user" type="String" assignTo="{!listDefaultValue}" default=""></apex:attribute>
<apex:attribute name="useDefaultValue" description="whether a default value to be shown or not" type="Boolean" assignTo="{!haveDefaultValue}" default="false"></apex:attribute>

<apex:selectList value="{!value}" size="1">
<apex:selectOptions value="{!items}"></apex:selectOptions>
</apex:selectList>
</apex:component>


The Component has only a selectList and a few attributes. Below are a list of attributes used for this component:

  • systemEntity: API name of the Object which has a picklist field
  • picklistField: API name of the Object's picklist field
  • value: This field should be bound to a property in parent Page's Controller
  • defaultLabel: Label of the default value shown to user, only visible when useDefaultValue is set to true.
  • defaultValue: Value of the default item shown to user, only visible when useDefaultValue is set to true.
  • useDefaultValue: A Boolean value tells the component whether to show a default value or not.
Now let's see how the Controller is look like:


public class picklistController {

//System object name, such as Account

private String systemObject;

public String getSystemObject() {

return systemObject;

}

public void setSystemObject(String value)

{

systemObject = value;

}

//picklist name such as "Type" of account object

private String picklist_Field;

public String getPicklist_Field() {

return picklist_Field;

}

public void setPicklist_Field(String value) {

picklist_Field= value;

}

//default item's value

public String listDefaultValue

{

get;

set;

}

//default item's label

public String listDefaultLabel

{

get;

set;

}

// whether the default item should be shown

public Boolean haveDefaultValue

{

get;

set;

}

public List getItems()

{

List entries_local;

if (systemObject != null)

{

//use GlobalDecribe to get a list of all available Objects

Map gd = Schema.getGlobalDescribe();

Set objectKeys = gd.keySet();

for(String objectKey: objectKeys)

{

//Iterate through all objects to locate selected Object

if (objectKey == systemObject.toLowerCase())

{

Schema.SObjectType systemObjectType = gd.get(objectKey);

Schema.DescribeSObjectResult r = systemObjectType.getDescribe();

Map M = r.fields.getMap();

Set fieldNames = M.keySet();

if (picklist_Field == null)

{

break;

}

//iterate through all fields of the object to locate the picklist field

for(String fieldName: fieldNames)

{

if (fieldName == picklist_Field.toLowerCase())

{

Schema.SObjectField field = M.get(fieldName);

Schema.DescribeFieldResult fieldDesc = field.getDescribe();

//extract the picklist values

entries_local = fieldDesc.getPicklistValues();

break;

}

}

}

}//end for

}

//Loading the picklist values and default item for our selectList

List options = new List();

//take care of Default value

if (haveDefaultValue == true)

{

if (listDefaultValue == null)

listDefaultValue = '';

if (listDefaultLabel== null)

listDefaultLabel = '--None--';

options.add(new SelectOption(listDefaultValue,listDefaultLabel));

}

//take care of picklist values

if (entries_local != null)

{

for(Schema.PicklistEntry picklistItem : entries_local)

{

options.add(new SelectOption(picklistItem.getValue(),picklistItem.getLabel()));

}

}

return options;

}

}



2 comments:

Kyle Roche said...

Hi, nice post. I was wondering how you are getting around the limit on the getpicklistvalues() method. This has been a problem for me especially w/ multiselects. I'm hitting the limit of 10 per class almost right away.

Thanks!
Kyle.

Justin said...

I am doing some custom work for a executive recruiting firm who profiles candidates by 16 different skills and experience categories with each category having about 10 or more values. I have created custom multi-select picklist fields on the contact record. For each contact/candidate, they select the values that apply. I want to create a relevance search query tool that allows the user to select the picklist values and responds with a list of condidates that best match the query. Any thoughts on an approach in salesforce

Post a Comment