Skip to Content

1. Introduction

Google maps has a Places Autocomplete API that can be used with any input field in CRM. This feature can save time and help validate addresses.

Once autocomplete is attached to a field, Google will present a list of suggested locations as you type.

/wp-content/uploads/2013/05/suggestions_221951.png

Upon selecting one of the suggestions, the address fields will be populated with the location details.

/wp-content/uploads/2013/05/filled_221952.png

The API homepage is at https://developers.google.com/maps/documentation/javascript/places#places_autocomplete

To add this feature, the BSP containing the autocomplete field must be enhanced. This instructions in this article assume that the reader knows how to find the component and view containing a chosen input field and enhance that view’s html file.

2. Including the Google Places Library

The Google Places library can be included by adding the following code to your BSP:

<script type=“text/javascript” src=“//www.google.com/jsapi”></script>

<script type=“text/javascript”>
/* Load google maps placesAPI */
google.
load(“maps”, “3”, {other_params: “libraries=places&sensor=false”, “callback”: mapsLoaded });

function mapsLoaded(){
   
/* Setup after loading Google Places library goes here */
}

</script>

3. Attaching Autocomplete to an Input Field

3.1 Getting the Field ID

First you will need the id of the input field you want to use. This can be easily obtained using the Firebug extension for Firefox or Internet Explorer Developer Tools. To start IE Developer Tools, press F12 on any webpage in Internet Explorer. To get Firebug go to http://getfirebug.com/.

Enter inspection mode and click on the field.

/wp-content/uploads/2013/05/firebuginspectionmode_221945.png

After you click on the field, the id attribute should be easy to find in the HTML panel. In the example screenshot below I have selected the Street / House Number field.

/wp-content/uploads/2013/05/firebugid_221947.png

The ID of your element will probably look something like ‘C17_W59_V60_V61_defaultaddressvalnode_struct.street’. The C##_W##_V##_V##_ part of the ID is dynamically generated and can change. To avoid any potential issues that could be caused by changing identifiers, I have used a jQuery selector that requires only the remainder of the ID.

3.2 jQuery and Selectors

To use the jQuery selectors, we need to include the jQuery library. This library can be pulled from Google by including the following tag in your BSP. This must come before any calls to jQuery functions.

<script src=“//ajax.googleapis.com/ajax/libs/jquery/1.6.3/jquery.min.js”></script>

jQuery uses $ as an alias for jQuery, however CRM also uses $ as a function name. Since we do not want to overwrite this function, we must return control of the $ variable to CRM using a call to jQuery.noConflict().

Example selector for a CRM input field with a partly dynamic identifier:

var streetInputField = jQuery(‘input[id*=”defaultaddressvalnode_struct.street”]’)[0];

In the code examples below there are several identifiers for different input fields. To use autocomplete with other fields in CRM, simply replace the identifiers in the example with the identifiers of other CRM fields.

The jQuery homepage is at http://api.jquery.com/

More information on jQuery selectors is available at http://api.jquery.com/category/selectors/

More information on the noConflict function is available at http://api.jquery.com/jQuery.noConflict/

3.3 Attaching Autocomplete to a Field

Attaching the autocomplete feature to an input field requires only a single line of code. This code should be placed in the mapsLoaded callback function to ensure that the API has been loaded before trying to use it:

var autocomplete = new google.maps.places.Autocomplete(inputField);

3.4 Listening for Events

The selection of a place suggestion will trigger the place_changed event. The following code can be used to listen for this event and should also be placed in the mapsLoaded callback.

google.maps.event.addListener(autocomplete,‘place_changed’, function()
{
   
/* Get place details */
   
var place = autocomplete.getPlace();
   
if (!place.geometry) {
       
return;
    }
  
    /* Do something with place information */

});

4. Complete Example

This code was written for the BuPaCreate.htm view from the component ICCMP_BP_DETAIL. In this example the values of several input fields are set using data from the place details. In order for these new values to persist, they must be saved to the buffer using the thtmlb_toggleInput function.

<script src=“//ajax.googleapis.com/ajax/libs/jquery/1.6.3/jquery.min.js”></script>
<script type=“text/javascript” src=“//www.google.com/jsapi”></script>
<script type=“text/javascript”>
/* jQuery noconflict is required for CRM */
var jqnc =
jQuery.noConflict();

/* Load google maps places API */
google.
load(“maps”, “3”, {other_params: “libraries=places&sensor=false”, “callback”: mapsLoaded });

/* Once the API has been loaded, we can use this callback function to attach the autocomplete feature */
function mapsLoaded(){

    /* Get input fields */
   
var streetInputField = jqnc(‘input[id*=”defaultaddressvalnode_struct.street”]’)[0];
   
var cityInputField = jqnc(‘input[id*=”defaultaddressvalnode_struct.city”]’)[0];
   
var postalInputfield = jqnc(‘input[id*=”defaultaddressvalnode_struct.postl_cod1″]’)[0];
   
var stateInputField = jqnc(‘input[id*=”defaultaddressvalnode_struct.region”]’)[0];
   
var countryInputField = jqnc(‘input[id*=”defaultaddressvalnode_struct.country”]’)[0];

  
    /* Attach the geo-autocomplete feature to the street input field */

   
var autocomplete = new google.maps.places.Autocomplete(streetInputField);


    /* Set up event listener for place selection */

    google.maps.
event.addListener(autocomplete, ‘place_changed’, function() {
       
/* Get place details */
       
var place = autocomplete.getPlace();
       
if (!place.geometry) {
           
return;
        }

        /* Loop through the address components for the selected place and fill
         the corresponding input fields in CRM */

       
var streetString = “”;
       
for (i = 0; i < place.address_components.length; i++){
           
var type = place.address_components[i].types[0];
           
if (type == ‘street_number’){
                streetString
= place.address_components[i].long_name + ” “;
            }
           
if (type == ‘route’){
                streetString
+= place.address_components[i].long_name;
            }
           
if (type == ‘locality’ || type == ‘administrative_area_level_3’){
                thtmlb_toggleInput(cityInputField);
                cityInputField.
value = place.address_components[i].long_name;
            }
           
if (type == ‘administrative_area_level_1’){
                thtmlb_toggleInput(stateInputField);
                stateInputField.
value = place.address_components[i].short_name;
            }
           
if (type == ‘postal_code’){
                thtmlb_toggleInput(postalInputfield);
                postalInputfield.
value = place.address_components[i].long_name;
            }
           
if (type == ‘country’){       
                thtmlb_toggleInput(countryInputField);
                countryInputField.
value = place.address_components[i].short_name;
            }
        }

        /* Either CRM or the Places API would restore the value of the
         autocomplete field after this event is fired, so we set the street name in a
         timeout shortly after we a selection is made. */

       
window.setTimeout(function() {
            thtmlb_toggleInput(streetInputField);
            streetInputField.
value = streetString;
            countryInputField.
focus();
        },
200);
    });
}

</script>

To report this post you need to login first.

16 Comments

You must be Logged on to comment or reply to a post.

  1. Saif Ali

    This is an exceptionally well written post – very concise and easy to follow.  This is a very useful feature. Thanks!

    (0) 
        1. ramanji gatla

          Hi Viswa, Thanks for attending my message.

          I copied the same in code in BuPaCreate.htm view from the component ICCMP_BP_DETAIL , but it is not  giving the Autocomplete option .

          I have Google maps RFC in  my system . Do i need to look into any settings in CRM or IE  level.

          or any Libray files need to upload into CRM system ?

          Notes :- Syntastically it is not giving any error.

          Please help me in this .

          regards,

          rama

          (0) 
          1. ramanji gatla

            It is working when we change the  context node identifies along with attribute .

            var streetInputField = jqnc(‘input[id*=”standardaddress_struct.street”]’)[0];

                 var cityInputField = jqnc(‘input[id*=”standardaddress_struct.city”]’)[0];

                 var postalInputfield = jqnc(‘input[id*=”standardaddress_struct.postl_cod1″]’)[0];

                 var stateInputField = jqnc(‘input[id*=”standardaddress_struct.region”]’)[0];

                 var countryInputField = jqnc(‘input[id*=”standardaddress_struct.country”]’)[0];

            Instead of

                 var streetInputField   = document.getElementById(‘<%= lv_Street %>’);

                 var cityInputField = jqnc(‘input[id*=”defaultaddressvalnode_struct.city”]’)[0];

                 var postalInputfield = jqnc(‘input[id*=”defaultaddressvalnode_struct.postl_cod1″]’)[0];

                 var stateInputField = jqnc(‘input[id*=”defaultaddressvalnode_struct.region”]’)[0];

                 var countryInputField = jqnc(‘input[id*=”defaultaddressvalnode_struct.country”]’)[0];

            Tks,rama

            (0) 
  2. Ralph Kemper

    Cool! Thank you for posting! I just tested it and in worked (sightly adopted for BP_ADDR).

    It is also possible to implement the solution without JQuery.

    Just use the following ABAP-syntax to get the IDs of the targetfields:

    <% data: lv_Street     type string. lv_Street = controller->get_id( in_id = ‘defaultaddressvalnode_struct.street’ ). %>

    and access the information in JS with

    var streetInputField   = document.getElementById(‘<%= lv_Street %>’);


    instead of:

    var streetInputField = jqnc(‘input[id*=”defaultaddressvalnode_struct.street”]’)[0];

    (0) 
  3. Dominik Riedl

    Hallo together,

    many thanks for this very well written post!

    But i still have a problem after implementing this feature in the BP_ADDR-Component. Navigation between different views in a viewset isn’t possible anymore when you use the latest versions of Mozilla firefox. But it still works when using IE 11.

    Has anyone the same problem? Or an idea how to fix this? This would be great 🙂

    many thanks for your help!

    Dominik

    (0) 
  4. ram ram

    Hi ,

    I have  tried the account creation for standard address  BP_ADDR/StandardAddress.htm

    But it is not working.

    same code I have used .

    <% data: lv_Street     type string. lv_Street = controller->get_id( in_id = ‘defaultaddressvalnode_struct.street’ ). %>

    <%–    var streetInputField = jqnc(‘input[id*=”defaultaddressvalnode_struct.street”]’)[0];–%>

         var streetInputField   = document.getElementById(‘<%= lv_Street %>’);

         var cityInputField = jqnc(‘input[id*=”defaultaddressvalnode_struct.city”]’)[0];

         var postalInputfield = jqnc(‘input[id*=”defaultaddressvalnode_struct.postl_cod1″]’)[0];

         var stateInputField = jqnc(‘input[id*=”defaultaddressvalnode_struct.region”]’)[0];

         var countryInputField = jqnc(‘input[id*=”defaultaddressvalnode_struct.country”]’)[0];

    regards,ram

    (0) 
  5. Wolfgang Mayer

    Hi Tom,

    have you tried this for search views as well? E.g. BP_HEAD_SEARCH/MainSearch? I tried to use the autocomplete function for the account name field (C32_W39_V132_search_parameters[1].VALUE1) getting values from an AJAX json call, however, it didn’t work. The logic itself is fine since it works without any issues on a Z BSP application outside CRM UI.

    Thanks & regards

    Wolfgang

    (0) 
  6. Glenn Michaels

    Hello All,

         We used this blog to implement this a few months back, we just implemented OSS note 2026791 for IE11 standard mode and now the java script call will not work on an IE11 browser (still works on IE10 or lower).   Looking for any assistance on how to correct.

        =”//www.google.com/jsapi” this API is not calling on IE11

    (0) 
    1. Glenn Michaels

      Working the issue with Google support desk, what we see is logging onto the CRM UI and creating account, the “enter a location” does not show.  But refresh the IE11 browser and it will show and continue to work as long as logged in.  But upon logging out and back in, the user has to refresh the browser the 1st time from the account create page.

      (0) 
    2. Glenn Michaels

      The SAP support desk was able to provide a solution, the JS is outside of standard support but upon hearing the browser refresh would resolve the issue, they had us adjust in the technical profile of the business role and check “Disable Automatic Delta Handling” which looks to resolve the need to refresh the IE11 browser  🙂

      (0) 
      1. Glenn Michaels

        another option to shutting off the disable automatic delta for the whole business role is to use SM31 and table BSPWDV_ADH_DSBL and put in the apps & views needed   BP_HEAD – BPHEADOVERVIEW, etc  as we found some other features in CRM need the automatic delta handling

        (0) 

Leave a Reply