Using Places Autocomplete for addresses in CRM
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.
Upon selecting one of the suggestions, the address fields will be populated with the location details.
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.
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.
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>
This is an exceptionally well written post - very concise and easy to follow. This is a very useful feature. Thanks!
This is a very useful feature highlighted and is very well written post.
This very useful document ....I tried using this in the Sales Pro its worked fine.
Thanks!
Hi Viswa, I have done the same as per wiki. But I am not getting the Autocomplete option .
Could you please help in this.
regards,ram
what error u r getting please let me know i can help you ..
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
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
Hi Viswa,
I am also trying to do auto address complete in SAP CRM grant management BP_ADDR component in standard address thru Canada Post. Auto address is working fine and i can select the values but after that when we click save or enter, data is not saved and values got cleared on enter. I used javascript code from canada Post website for Auto address complete Any suggestions.
I tried to use thtmlb_toggleInput(stateInputField); for my fields but it didn't help.
This below code is from Canada Post website: mainly how to transfer those input values to CRM ?
<script type="text/javascript">
var streetInputField = document.getElementById('<%= lv_Street %>');
var poboxInputField = document.getElementById('<%= lv_pobox %>');
var regionInputField = document.getElementById('<%= lv_region %>');
var cityInputField = document.getElementById('<%= lv_city %>');
var countryInputField = document.getElementById('<%= lv_country %>');
var fields = [
{ element: streetInputField, field: "", mode: pca.fieldMode.SEARCH },
{ element: streetInputField, field: "Line1", mode: pca.fieldMode.POPULATE },
{ element: "street-address2", field: "Line2", mode: pca.fieldMode.POPULATE },
{ element: cityInputField, field: "City", mode: pca.fieldMode.POPULATE },
{ element: regionInputField, field: "Province", mode: pca.fieldMode.POPULATE },
{ element: poboxInputField, field: "PostalCode" },
{ element: countryInputField, field: "Country", mode: pca.fieldMode.COUNTRY }
],
options = {
key: "key of canada post"
},
control = new pca.Address(fields, options);
console.log(window.addressComplete);
window.addressComplete.listen( 'load', function(control)
{
control.listen("populate", function (address)
{
cityInputField.value = address.City;
thtmlb_toggleInput(cityInputField);
alert (" hi i an here in load");
alert("In Load ");
}) ;
});
console.log(addressComplete.controls[0]);
addressComplete.controls[0].listen('populate', function (address) {
alert("In Load new");
});
//addressComplete.listen('load', function(control) {
control.listen("populate", function(address) {
document.getElementById("line1").value = address.Line1;
alert("In Load Populate");
});
//});
addressComplete.listen('ready', function() {
addressComplete.setCulture("fr-CA");
alert("In ready");
});
window.setTimeout(function() {
thtmlb_toggleInput(streetInputField);
streetInputField.value = address.Line1;
countryInputField.focus();
}, 200);
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];
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
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
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
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
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.
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 🙂
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
Awesome post..Thanks
Dear All
I am also trying to do auto address complete in SAP CRM grant management BP_ADDR component in standard address thru Canada Post. Auto address is working fine and i can select the values but after that when we click save or enter, data is not saved and values got cleared on enter. I used javascript code from canada Post website for Auto address complete Any suggestions to resolve this issue
I tried to use thtmlb_toggleInput(stateInputField); for my fields but it didn't help.
This below code is used fro auto address complete from Canada Post website:
<script type="text/javascript">
var streetInputField = document.getElementById('<%= lv_Street %>');
var poboxInputField = document.getElementById('<%= lv_pobox %>');
var regionInputField = document.getElementById('<%= lv_region %>');
var cityInputField = document.getElementById('<%= lv_city %>');
var countryInputField = document.getElementById('<%= lv_country %>');
var fields = [
{ element: streetInputField, field: "", mode: pca.fieldMode.SEARCH },
{ element: streetInputField, field: "Line1", mode: pca.fieldMode.POPULATE },
{ element: "street-address2", field: "Line2", mode: pca.fieldMode.POPULATE },
{ element: cityInputField, field: "City", mode: pca.fieldMode.POPULATE },
{ element: regionInputField, field: "Province", mode: pca.fieldMode.POPULATE },
{ element: poboxInputField, field: "PostalCode" },
{ element: countryInputField, field: "Country", mode: pca.fieldMode.COUNTRY }
],
options = {
key: "key of canada post"
},
control = new pca.Address(fields, options);
console.log(window.addressComplete);
window.addressComplete.listen( 'load', function(control)
{
control.listen("populate", function (address)
{
cityInputField.value = address.City;
thtmlb_toggleInput(cityInputField);
alert (" hi i an here in load");
alert("In Load ");
}) ;
});
console.log(addressComplete.controls[0]);
addressComplete.controls[0].listen('populate', function (address) {
alert("In Load new");
});
//addressComplete.listen('load', function(control) {
control.listen("populate", function(address) {
document.getElementById("line1").value = address.Line1;
alert("In Load Populate");
});
//});
addressComplete.listen('ready', function() {
addressComplete.setCulture("fr-CA");
alert("In ready");
});
window.setTimeout(function() {
thtmlb_toggleInput(streetInputField);
streetInputField.value = address.Line1;
countryInputField.focus();
}, 200);
Hello,
Does anyone know whether an address autocomplete feature like those described above could be added to Environment, Health, and Safety (EHS) Incident Management?
James