Display a Multi-picklist as Checkboxes

Nerding, SalesForce on December 15th, 2008 No Comments

Normally I wouldn’t post a code sample regarding something (seemingly) so straightforward, but this took myself and a contractor too much time to figure out.  Multi-picklist fields in SalesForce.com are many-to-many relationships between a record and a set of strings.  You can define what options are available in the object definition, and then select which options apply to each record as you edit it.

VisualForce, SalesForce’s XML-based markup language, allows you to instantiate an inputField of a multi-picklist (or multivalue-picklist, as some call it) as easily as all the others.  However, and this is starting to get to the fun part, if you’re viewing it on a tab in a tabPanel which the SF engine does not consider active, then it displays with a width: 35px inside of some elements that you can’t control, so it looks too narrow and you can’t use it.  In the current project, we’re using Javascript to switch tabs so SF doesn’t know about it, ergo doesn’t display the multi-picklists correctly on most tabs.

The client wanted them displayed as a set of checkboxes (via selectCheckboxes) anyway, so we set to work trying to make it happen.  I’ll spare you the details, but it was kind of a challenge to dig out all the necessary nuggets.  Here’s a generalized, context-free code snippet that should save you some time if you’re trying to do the same thing.

private List<SelectOption>
  generateMPOptions(List<Schema.PicklistEntry> ple) {
List<SelectOption> options = new List<SelectOption>();
for( Schema.PicklistEntry f : ple) {
  options.add(new SelectOption(f.getValue(), f.getLabel()));
} return options;
}
public String[] MPItems { get {
  String[] selected = new List<String>();
  List<SelectOption> sos = this.MPOptions;
  for(SelectOption s : sos) {
    if (this.object.MPField.contains(s.getValue()))
  selected.add(s.getValue());
}
return selected;
} public set {
  String selectedConcat = '';
  for(String s : value) {
    if (selectedConcat == '') selectedConcat += s;
  else selectedConcat += ';' + s;
}
this.object.MPField = selectedConcat;
upsert this.object;
}} 
public List<SelectOption> MPOptions {get {
  return this.generateMPOptions(Object.Field.getDescribe().getPicklistValues());
} private set;}

And here’s the VisualForce element:

<apex:pageBlockSectionItem >
  <apex:outputtext value="Field Label"/>
  <apex:selectCheckboxes value="{!MPItems}" layout="pageDirection">
    <apex:selectOptions value="{!MPOptions}">
    </apex:selectOptions>
  </apex:selectCheckboxes>
</apex:pageBlockSectionItem>

I ended up adding some hidden fields to the VisualForce page to make sure the controller queried the fields prior to use (that’s right, you weren’t looking and got gooey abstraction barrier all over your shoe). I also came immediately up against the limits on using getDescribe() – currently 10 per instantiation – so I made some additional member variables to hold the field option values. Apparently those limits get a little better the in Winter 09′ edition.

Tags: , , ,

No Responses to “Display a Multi-picklist as Checkboxes”

Leave a Reply