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.
<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: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>
- 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.
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
{
List
if (systemObject != null)
{
//use GlobalDecribe to get a list of all available Objects
Map
Set
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
Set
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
//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;
}
}
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.
ReplyDeleteThanks!
Kyle.
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
ReplyDeleteHi,
ReplyDeleteI am trying to implement the picklist controller as you have mentioned above. I am getting an error in the function definition line of getItems()
When I change the def to:
public List getItems(), i get error in the other lines too that have Map and set kind of values. Since I am a novice in Java and Apex as a whole. Could you help me figure this out.
Thanks,
After some struggle, i have been able to figure out the collections to be used.
ReplyDeleteThis is how the controller looks like now(w/o errors):
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;
}
}
Do let me know if you see any issues.
Thanks
compile error line 34
DeleteAm getting error on public list getItems()
ReplyDeleteplz help me...am new to apex coding
This seems to be publishing error, the signs < > that are html reserved characters are omitted.
ReplyDeletethe method should be like:
public List<SelectOption> getItems()
I will update the post as soon as possible.
Thank you!!!
ReplyDeleteThere are several "mistakes" in the controller code for the component as it is published - the signature definition for the getItems() method as you have mentioned, but also Map variables, etc.
ReplyDeleteThe primary question I have is : How do you get the selected picklist value to use in the controller of the "parent" page? (aka the page in which the custom component is used)
The need to access a value from a custom component in the component's "parent" page is very important, especially if your component contains a picklist, etc.
Sam - can you PLEASE post the code for the page in which you used this component so we can all see exactly how the two can work together?
Thanks in advance!
There are several "mistakes" in the controller code for the component as it is published - the signature definition for the getItems() method as you have mentioned, but also Map variables, etc.
ReplyDeleteThe primary question I have is : How do you get the selected picklist value to use in the controller of the "parent" page? (aka the page in which the custom component is used)
The need to access a value from a custom component in the component's "parent" page is very important, especially if your component contains a picklist, etc.
Sam - can you PLEASE post the code for the page in which you used this component so we can all see exactly how the two can work together?
Thanks in advance!
Bind a parent page property to the component's value attribute and you will be able see get what user selects on the parent page.
ReplyDeletepublic class picklistController {
ReplyDelete//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=new list();
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;
}
}
This will not throw error...when you save
hi sam,
ReplyDeletei have a doubt in the line below. what this line says?? bound to a parent page's controller, where this component is used??? U mean this in the below line.. please reply, it will be very useful for me if u answer this...
value: This field should be bound to a property in parent Page's Controller...
thanks,
venkat
Can anybody tell me how to retrieve values of an object from custom controller class into it's corresponding visualforce page??please
ReplyDeleteas long as you add the object as a property to the controller class, you can access it via merge fields on the visualforce page: {!propertyname.fieldname}
ReplyDelete