Saturday, May 9, 2020

Five Easy Steps to Implement Autocomplete in Salesforce Visual Force Page


Almost all website uses Autocomplete function when doing search. Autocomplete gives users suggestions on what you could be searching for.

For example, if you type “sales” in Google search box, you can see a list of most popular searched words or sentences listed under the search box; if one of them is what you want to search, just move mouse to the word and click it. This saves you time and helps you avoiding typo.

When doing Visual Force page design, developers find Salesforce does not provide native autocomplete function.


In this blog, I will how to implement Autocomplete in Visual Force Page with the help of Jquery UI STEP BY STEP.

If you don't  have time to read the details of the implementation, do the following and your code should work.

  • Copy the code of step 1, 3
  • Refer to Step 2, find search input text <apex:inputText> component in your Visual force Page, add class "contact_search" to this component, and copy line 4 of section 3 to your code.
  • Copy code of step 4, change line 31 of code in section 4 to your own Apex class method.
  • Refer to step 5, make sure your Apex Class method works. (You can't copy the code for Apex method. 😃



1. Add JQuery JavaScript library and css Style to Visual Force Page
Within Visual Force Page, this can be done by referencing static resource or simply by referencing the library through <script> tag. I prefer just add the line right after <apex:page>  

Style ui-autocomplete will be used in displaying the autocomplete list. It is very important.


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
<apex:Page controller="customController">
    <style type="text/css">
    .ui-autocomplete {
        max-height: 80%;
        overflow-y: auto;
        overflow-x: hidden;
        min-width: 250px;
    }
    </style>
    <script src="https://code.jquery.com/jquery-1.8.2.js"></script>
    <script src="https://code.jquery.com/ui/1.9.0/jquery-ui.js"></script>
    <link rel="stylesheet" href="https://code.jquery.com/ui/1.9.1/themes/base/jquery-ui.css"/>
      ......


2. Add <apex:ActionSupport> component to search <apex:inputText> component.

The following code present user an input text box and a search button.



1
2
3
4
5
<apex:outputPanel id="searchPanel">
    <legend class="slds-form-element__legend slds-form-element__label ">Search</legend>
    <apex:inputText value="{!searchString}" styleClass="slds-m-right_x-small"/>
    <apex:commandButton action="{!search}" value="Search" reRender="formId" status="spinner"  id="searchButtonId" />
</apex:outputPanel>
Just add <apex:actionSupport> to <apex:inputText> component and add class “contact_search” to <apex:inputText> component.
Note:  “contact_search” will be used in JQuery to identify which input text box to have list value populated.

1
2
3
4
5
6
7
<apex:outputPanel id="searchPanel">
    <legend class="slds-form-element__legend slds-form-element__label ">Search</legend>
    <apex:inputText value="{!searchString}" styleClass="contact_search slds-m-right_x-small">
        <apex:actionSupport event="onchange" rerender="refreshAutocomplete"/>
    </apex:inputText>
    <apex:commandButton action="{!search}" value="Search" reRender="formId" status="spinner"  id="searchButtonId" />
</apex:outputPanel>


3. Add <apex:actionFunction> component called “refreshAutocomplete”.
<apex:actionFunction component that provides support for invoking controller action methods directly from JavaScript code using an AJAX request.

You can add the following line to line just right after <apex:form>


1
2
3
<apex:form id="formId">
   <apex:actionFunction name="refreshAutocomplete" id="refreshAutocomplete" 
    rerender="autocompletePanel"/>


In step 2, input text box change triggers AJAX request refreshing component id “refreshAutocomplete”.
So we add a <apex:actionFunction> with id=”refreshAutocomplete”. When this component refreshes, it will rerender component “autocompltePanel


4.Add <apex:outputPane id=”autocompletePanel”> with JQuery JavaScript functions.
Copy the following line to the end of your VF page. It could be out of </apex:form> tag.
This is the core function of autocomplete with JQuery. I will explain line by line after JavaScript code.

NoteautocompletePanel, it matches the one in step 3.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
    <apex:outputPanel id="autocompletePanel">
        <script type="text/javascript">

            $(function() {
                try {
                    var ac = $( "[class*='contact_search']" ).autocomplete({
                        minLength: 2,
                        source: function(request, callback){
                            var term = request.term;
                            queryContactCallback(term, callback);
                        },
                        select: function( event, ui ) {
                            $( "input[class*='contact_search']" ).val(ui.item.label);
                            return false;
                        }
                    }).data( "ui-autocomplete" )._renderItem = function( ul, item ) {
                        return $( "<li>" )
                        .append( "<a class='slds-text-title'>"+ item.label + "</a>" )
                        .appendTo( ul );
                    };
                } catch(e) {
                    console.log('error:' + e);
                 }
            });

            function queryContactCallback(query, callback)
            {
                var data = [];

                Visualforce.remoting.Manager.invokeAction(
                    '{!$RemoteAction.COT_ContactController.getAutoCompleteContact}',
                    query,
                    function(lstresult, event){
                        for (var n=0; n<lstresult.length; n++){
                            var result = {
                                value: lstresult[n],
                                label: lstresult[n]
                            };
                            data.push(result);
                        }
                        callback(data);
                    }
                );

            }

        </script>
    </apex:outputPanel>

Line 6 : var ac = $( "[class*='contact_search']" ).autocomplete({
Make sure the class value matches the input text class added in step 2. It is ‘contact_search’.

Line 7: minLenght: 2
This line means only when there are at least to characters entered in the box, the Remote call will be made to the controller.

Line 9: var term = request.term;
requet.term is what user enters in input text box.

Line 10: queryContactCallback(term, callback);
This lines calls JavaScript function queryContactCallback.  queryContactCallback is function at line 26.

Line 12 to Line 14:
            select: function( event, ui ) {
                            $( "input[class*='contact_search']" ).val(ui.item.label);
                            return false;
                        }
         
This four lines handle when user select a value from autocomplete dropdown list.

It basically gets the item label and put in input text box.



Line 16 to Line 19: 
            data( "ui-autocomplete" )._renderItem = function( ul, item ) {
                    return $( "<li>" )
                    .append( "<a class='slds-text-title'>"+ item.label + "</a>" )
                   .appendTo( ul );

Do you still remember "ui-autocomplete"?  We added it to VF Page in step 1.  Yes, it is used in line 16.
Line 16 to Line 19 get the return values from controller method and populate into a list. If needed, developer can modify this line .append( "<a class='slds-text-title'>"+ item.label + "</a>" )  to make the dropdown more fancy.

Line 26: Function queryContactCallback
This method calls the controller method and return list value.
{!$RemoteAction.customController.getAutoCompleteContact}',
This line tells Salesforce to call method getAutoCompleteContract in Apex Class called “customController”.
If there are multiple parameters passing to the method, you can do like this:

            Visualforce.remoting.Manager.invokeAction(
                        {!$RemoteAction.customController.getAutoCompleteContact}',
                        parameter1,
                        parameter2,
                        function(lstresult, event){

Line 34 to Line 39: Return values from Controller method call
It iterates the return list value from controller and put in list. 
You can define your own attribute by replacing value, label.
In the following example, you can set attribute to firstname and lastname, but make sure in selection function Line 13, the right attribute is referenced, change ui.item.label to the right attribute ui.item.firstname.


1
2
3
4
5
6
7
 for (var n=0; n<lstresult.length; n++){
     var result = {
         firstname: lstresult[n],
         lastname: lstresult[n]
     };
     data.push(result);
 }

5.Add Controller Method

This is standard salesforce method. Don’t forget adding @RemoteAction annotation and setting method as Static.





1
2
3
4
5
6
7
8
9
    @RemoteAction
    public Static List<String> getAutoCompleteContact(String searchString)
    {
        List<String> result = new List<String>();

        ....

        Return return;
    }

Let's take a look how autocomplete looks like. Look pretty good!



No comments:

Post a Comment