Tuesday, January 12, 2016

[Salesforce / Visualforce] Input Lookup Custom Component

Have you ever needed a VisualForce lookup input field without using a lookup field from another "fake" object?

I did, and now I have an easy to use VisualForce component that does the trick (almost all the trick).

Here is the GitHub repository that contains the component.

The components simply replicates what the standard lookup field does, with 2 important differences:
  • We have to use a custom Apex class to store the ID value (simple data types as String or ID are passed by value rather than reference, so it is impossibile to change the component's parameter value on the fly, see Bob Buzzard post Updating Attributes in Component Controller)
  • If you change the value of the "name" of the lookup field and this matches more than one record, the form submission is canceled and a picklist with all the values is shown (so the user can choose the correct record)

The first class is the ID value container:

public class IDCarrier {
    public IDCarrier(){}
    public IDCarrier(ID value){
        this.value = value;
    }
    public ID value{get;Set;}
}

In your test controller, TestLookupController:
public class TestLookupController {
    public IDCarrier idValue1{get;set;}
 public IDCarrier idValue2{get;set;}
    public TestLookupController(){
        this.idValue1 = new IDCarrier([Select Id From Account Limit 1].Id);
  this.idValue2 = new IDCarrier();
    }
    public void submit(){
  //...
 }
}

You are creating 2 ID fields, one populated with a valid Account Id, the other without any value.

And now in the test page use the component:
<apex:page controller="TestPageController" >
    <apex:form >
        <apex:pageblock>
            <apex:pageBlockButtons location="bottom">
             <apex:commandButton value="SUBMIT" action="{!submit}" />
            </apex:pageBlockButtons>
         <apex:pageblocksection columns="2">
                <apex:pageBlockSectionItem>
                    <apex:outputLabel>Account lookup</apex:outputLabel>
                 <c:inputLookup sobject="Account" value="{!idValue1}"/>
                </apex:pageBlockSectionItem>
                <apex:pageBlockSectionItem>
                    <apex:outputLabel>Selected Account ID:</apex:outputLabel>
                 <apex:outputText value="{!idValue1.value}"/>
                </apex:pageBlockSectionItem>
                
                <apex:pageBlockSectionItem>
                    <apex:outputLabel>Contact lookup</apex:outputLabel>
                 <c:inputLookup sobject="Contact" value="{!idValue2}"/>
                </apex:pageBlockSectionItem>
                <apex:pageBlockSectionItem>
                    <apex:outputLabel>Selected Contact ID:</apex:outputLabel>
                 <apex:outputText value="{!idValue2.value}"/>
                </apex:pageBlockSectionItem>
            </apex:pageblocksection>
        </apex:pageblock>
    </apex:form>
</apex:page>

The component has only 2 parameters:
  • sobject: this is the Sobject API Name (with full prefix name if needed, mandatory)
  • lookup: this is the value field (of type IDCarrier). This is field is not mandatory (in case it is not set, the submit won't set any value)

In the test page we have now 2 input lookup custom components, one of type Account and the other of type Contact:


If you click the "search" button the standard lookup search page appears (it is configurable with the standard object's search layout options).

Once you select a new value for both input lookups and hit the SUBMIT button, the corresponding controller variables idValue1 and idValue2 are correctly updated:


If you type a different name value (without using the lookup window):


Then hit SUBMIT:


The first "%Sale%" Account found is linked to the input lookup component.
If no object is found by the query, the result is simply null (on the IDCarrier.value member).

That's it!