Tuesday, July 24, 2018

Custom Sitecore Field: Google Maps Autocomplete

Maps are everywhere.  Most modern web designs often include some kind of map functionality whenever points of interest are involved.  If you've ever built a template that houses location data (stores, events, etc), you'd likely included latitude and longitude data points as Single-Line Text fields on the relevant Sitecore template.

However, this approach still forces the Content Author / Marketer to discover the latitude and longitude points based on an address themselves.

While this isn't too difficult to manage, we wanted to make eliminate this step - and make it easier for the author to ensure they're getting reliable latitude/longitude points every time without the need for any external lat/long discovery.

We've seen other examples (Google Map Location Picker Field or  this older module) exist where maps selectors are used (many of which are pretty old now!), but none that strictly use the Google Maps Autocomplete API.
If you're looking for some code on how to achieve this - you've come to the right place!

GOAL

Create a custom Sitecore Field Type integrated with Google Maps Places Autocomplete API that automatically retrieves and stores Latitude and Longitude points based on an inputted address.

Injecting Scripts to the Content Editor

In order to consume the Google Maps Autocomplete API, our page will need to render a script tag referencing the API in the Content Editor.  Luckily, Sitecore allows us to inject custom styles and scripts to the Content Editor as needed.  In this case, there are two script tags we'll need to add:
    1. The Google Maps Autocomplete API library
    2. A custom Javascript file with methods that initialize, geolocate, and fill in the Latitude and Longitude field

Our patched config entries include a new pipeline:

In our pipeline, we loop through the resource definitions set in the config and process new script tags to be added when the content editor loads:

New Template Field Type Item

Our Autocomplete Address Template Field Type is defined in the Core DB:


The Control field value is set to customfieldtypes:AutocompleteAddress. This means two things:
  1. We'll need to register customfieldtype as a new controlSource
  2. A new AutocompleteAddress class which inherits from the Sitecore.Web.UI.HtmlControls.Control class. 

Template Field Type Code and Config

The config entry to define a new control is pretty straightforward:


The corresponding control code:
In this approach, our Control code actually creates three text boxes on the fly (Address, Latitude, Longitude).  The Address text box control will act as the autocomplete which interacts with the API.

Once an address is selected from the autocomplete selections - the custom JS retrieves the address's latitude and longitude points.  These lat/long values will be mapped to the two additional text boxes, then stored as a NameValueCollection string in the raw value of the Autocomplete field type in the following string format:

Address=2104 North Clark Street, Chicago, IL, USA&Latitude=41.920385&Longitude=-87.637572

To hook the Address textbox to our custom script we're simply adding an onfocus attribute 'javascript:autoCompleteAddress.initAutocomplete' to the Address text box control.

The custom JS handles the rest of the interaction to call the API and populate the Latitude and Longitude textbox controls with the right values.


Utilizing the Field Value

When it's time to use the latitude/longitude points on the front-end, we utilize a StringExtension method to parse the necessary values.

Full source for this implementation can be found here:
https://github.com/strezag/GoogleMapsAutocompleteCustomSitecoreField

While this was built using the latest version of Sitecore (v9 Update-2 at the time of this post), we were able to verify this on a local copy of 8.2.  My guess is that this probably would work for even earlier versions (even if it's just a few tweaks).

Feel free to grab a copy and modify it to your own specs!