Let’s Build an AutoSuggest Lightning Component with Google Places API

I had the challenge of building an input form that brings up a list of cities as you type. One that has the coordinates of each city – because I’ll need to enter that into a map. An “auto-suggest” or “auto-complete” city input – inside a custom form inside Salesforce. It turns out, that it wasn’t so bad.

We’re using Google Places for our API and Lightning Components for our Front End. If you’re not familiar with Lightning, check their documentation.

Our component will look like below.

lightning input autosuggest

Ready to start coding? Let’s start.

API Setup

Let’s get Google going. Remember, each time a user type a character – it will ping Google for suggestions. Also, the suggestions does not contain coordinates for each item, so we will need to ping the API as soon as the user selects a place.

I’m going to assume that you know how to get an API key from your Google account. If not, here is their API documentation.

The first part is getting the suggestions. Below is the URL that we need for that:

https://maps.googleapis.com/maps/api/place/autocomplete/json?input=TERM&key=YOURKEY

Looking at the above, we’re passing in what the user is typing where it says “TERM”.

The second part is when the user selects an item:

https://maps.googleapis.com/maps/api/place/details/json?placeid=PLACEID&key=YOURKEY

The above shows a “placeid” parameter that we get from each suggestion. So when the user clicks – we pass the id to the above URL.

Now that we have our Places API setup. Let’s move forward to our Salesforce code.

Build the Apex Class

One thing to note is that our Lighting components cannot reach out to Places API directly. Google doesn’t allow CORS to their endpoints – so we simply cannot do this. Nor would we want to – because if we do this via JavaScript – we will be exposing our keys. So we need the server to do the calls. In Salesforce, we use Apex.

We also have to add “maps.googleapis.com” to the remote site settings in Salesforce. To do this, go to “Setup” > “Security” > “Remote Site Settings”.

Click on “New Remote Site” and add the required fields:

Remote site settings - Salesflorce

Now, let’s create our Apex Class. Copy the code below and add it to your Class:

Note the two methods that have @AuraEnabled: getSuggestions() and getPlaceDetails(). These are the two endpoints we will be calling from our JavaScript in our Lightning component. Both methods are quite explanatory, they simply accept parameters from our front end, go out to Google and return the results.

Don’t forget to add your API key to the method getKey().

Let’s move on.

Our Component

The component (.cmp file) will need a few things. First, we need a couple of attributes to hold our values. One for location and one called “predictions”. The location is the value that will be in our input, while the predictions is what will show directly beneath it – in an unordered list. Note that this is what comes back from our API.  So add that first to your component.

We’re using “lightning:input” for our form field. We add a label, name, an aura:id, a value and an onchange attribute. The label and name is pretty straightforward, the aura:id – is simply a way for us to reference it in our controller.

The value – binds the input to our attribute “location”. Which we show as “v.location“.

The onchange – we’re attaching to a function in our controller named getCities(), which we refer to as “c.getCities“.

We’re using an unordered list for our suggestions. So we use the code below:

Notice we wrap it an “aura:if”  – which determines if our predictions object has more than zero length. Remember, predictions is coming straight from the API.

Then we have an “aura:iteration” for each prediction to show up in a list item > anchor tag. Each anchor tag has an “onclick” (which we’re attaching to getCityDetails()) and a “data-placeid” (I’ll explain later).

The Controller

So remember in our component we have 2 methods: getCities() and getCityDetails()? Those both go in our controller.

Our getCities() method is called every time we change the input field. Meaning – every time we type a letter, it calls this method.

First it sets up an object called “params“, which has one item in it called “input“. This is what we’re sending our Apex class through the use of helper.callServer(). I’ve explained all about this handy helper in my previous post. Once our Apex responds with some suggestions – we parse it through JSON.parse() and set it to our component attribute called “predictions”.

So our UL of suggestions will only populate if there’s a response from the server.

Finally, getCityDetails() get’s triggered when we choose an item from our UL (or click the anchor tag).

Remember the “data-placeid” attribute that we have for each anchor tag? This is where we will need it. We grab the value of “data-placeid” (which is the Place Id required for our API) through the event.currentTarget. We then create the “params” object like we did above.

We then do a helper.callServer() and when finished, we parse then set the v.location (the input value) and v.predictions back to empty.

I specifically needed the coordinates for the selected location, which can easily be grabbed from the response. You can do something similar.

The Final Product:

Below is a short screengrab of the final output. The lightning:input makes our field look better than just a regular input. Also, this is a “barebones” solution for an auto suggest field. You can greatly enhance by adding icons, additional description for each place, maybe some more events (like on tab, enter etc).

Lightning Auto Suggest

5 Comments

  1. Hi Michael, I’m getting this error when implementing this on my own org: helper.callServer is not a function.
    What do you supposed I am missing here? TIA!

    Reply

Leave a Comment.