Tweet |
This blog entry shows how to create your own visualforce lookup page backed by a custom controller that gives you full control.
My basic page for demonstrating custom lookup functionality is shown below:
The Lookup link pops up the lookup window. Search text is entered into the input field and clicking the Go button returns the results into the results section:
Clicking the name populates the lookup text field on the main page, and to prove that it is working, clicking the Get Contacts button retrieves the contacts associated with the account:
The first point to mention regarding lookups is that there are actually two fields that are filled in on the target page when you select a lookup result. The name of the selected item is displayed in the visible field, but names are not unique so this is not enough information to uniquely identify the chosen item. Thus there is a hidden field that captures the the ID of the selected record.
Below is a snippet of a VisualForce page that contains my custom lookup combination field. For the sake of simplicity I've chosen to use a clickable link to launch the lookup dialog.
<apex:pageBlock title="Lookup"> <apex:pageBlockSection columns="1"> <apex:pageBlockSectionitem > <apex:outputLabel value="Account"/> <apex:outputPanel > <apex:inputHidden value="{!accountId}" id="targetId" /> <apex:inputText size="40" value="{!accountName}" id="targetName" onFocus="this.blur()" disabled="false"/> <a href="#" onclick="openLookupPopup('{!$Component.targetName}', '{!$Component.targetId}'); return false">Lookup</a> </apex:outputPanel> </apex:pageBlockSectionitem> </apex:pageBlockSection> <apex:pageBlockSection > <apex:pageBlockSectionitem > <apex:commandButton value="Get Contacts" action="{!findContacts}"/> </apex:pageBlockSectionitem> </apex:pageBlockSection> </apex:pageBlock>
Digging into the markup, we can see that as well as the text field and link, the hidden field to capture the link is also present. When the user clicks the link, the following javascript is executed to open the popup. Note that the HTML element ids are passed as parameters to the popup page - this allows the popup to locate the fields to populate when the user makes a selection. Note also that the javascript function to close the popup window is located in the main page, not the popup page. This is required as browsers often only allow a window to be closed by the same page that opened it.
<script> var newWin=null; function openLookupPopup(name, id) { var url="/apex/LookupExamplePopup?namefield=" + name + "&idfield=" + id; newWin=window.open(url, 'Popup','height=500,width=600,left=100,top=100,resizable=no,scrollbars=yes,toolbar=no,status=no'); if (window.focus) { newWin.focus(); } return false; } function closeLookupPopup() { if (null!=newWin) { newWin.close(); } } </script>
Now we move on to the popup VisualForce page. This consists of a criteria section and a results table. Clicking the Go button invokes a controller action method that executes a SOSL query to retrieve all accounts matching the input string. The VisualForce markup for the results table is shown below.
<apex:pageBlock > <apex:pageBlockSection columns="1"> <apex:pageBlockTable value="{!accounts}" var="account"> <apex:column headerValue="Name"> <apex:outputLink value="#" onclick="fillIn('{!account.Name}', '{!account.id}')">{!account.Name}</apex:outputLink> </apex:column> <apex:column headerValue="Street" value="{!account.BillingStreet}"/> <apex:column headerValue="City" value="{!account.BillingCity}"/> <apex:column headerValue="Postcode" value="{!account.BillingPostalCode}"/> </apex:pageBlockTable> </apex:pageBlockSection> </apex:pageBlock>
As you can see, the account name column is actually a link that invokes a JavaScript function shown below:
function fillIn(name, id) { var winMain=window.opener; if (null==winMain) { winMain=window.parent.opener; } var ele=winMain.document.getElementById('{!$CurrentPage.parameters.namefield}'); ele.value=name; ele=winMain.document.getElementById('{!$CurrentPage.parameters.idfield}'); ele.value=id; CloseWindow(); } function CloseWindow() { var winMain=window.opener; if (null==winMain) { winMain=window.parent.opener; } winMain.closeLookupPopup(); }
This JavaScript is the glue between the two pages - it fills in the HTML elements in the main page and closes the popup window.
The pages and controllers can be downloaded here. Simply unzip into the src directory of your Force.com project in the IDE.