How to Use the Google Places API in a Sencha Touch Application

6 min read

Originally published July 30, 2014

I've been developing an application that uses the Google Maps API and needed to include the Google Places API as well. I had a bit of trouble with the integration so as always I wanted to provide a guide on how you can implement it as well, hopefully saving you a bit of hassle.

If you don't know what Google Places is, it's a service that provides information about places. This includes information like a formatted street address, the vicinity of the area, latitude and longitude of the location and so on. In my case, I needed users to enter an address and then retrieve the latitude and longitude of the location from that. I also wanted to provide auto complete functionality so users don't have to type out the entire address – fortunately Google Places takes care of this for us as well.

Before I continue on with the tutorial I must say that mine is perhaps not the best solution out there. I took a bit of time to research to try and do things the right way, the 'Sencha Touch Way', but ended up resorting to use a little bit of a dirty hack. I'll explain more when I get to it, but if you know how to do it better please let me know in the comments!

1. Including the API

First of all you will need to include the Google Places API. You may already have the Google Maps API included which looks like this:

<script
  type="text/javascript"
  src="http://maps.google.com/maps/api/js?sensor=true"
></script>

To make the Google Places API available just add &libraries=places to the end of the URL:

<script
  type="text/javascript"
  src="http://maps.google.com/maps/api/js?sensor=true&libraries=places"
></script>

2. Getting sneaky with input fields

Next you're going to bring up your form view, i.e:

var locationComplete;

Ext.define('MyApp.view.MyForm', {
     extend: 'Ext.form.Panel',
    requires: ['Ext.form.FieldSet', 'Ext.field.Number', 'Ext.field.Select', 'Ext.field.DatePicker'],
     xtype: 'myform',

     //and so on

Again, I've declared a global 'locationComplete' variable outside the view definition which isn't exactly great either and a bit of a hack but it works. That's only the beginning though, this is where it gets a little worse.

As you will see we need to grab a reference to the input field where we want the auto complete magic to happen – but no matter what I seemed to do with Sencha Touch's selectors I couldn't get auto complete working. So I resorted to manually creating the input field with my own id and referencing it that way. As I mentioned before, if you know how to get the auto complete playing nicely with Sencha Touch please let me know… until then this works as the form item:

{
    html: '<div class="x-container x-field-text x-field x-label-align-top x-field-labeled x-form-label-nowrap x-empty" id=""><div class="x-form-label" id="" style="width: 100% !important;"><span id="ext-element-251">Address</span></div><div class="x-component-outer" id=""><div class="x-unsized x-field-input" id=""><input class="x-input-el x-form-field x-input-text" type="text" id="locationField" name="locationPoint" maxlength="50" placeholder=""><div class="x-field-mask" style="display: none !important;" id=""></div><div class="x-clear-icon" id=""></div></div></div></div>'
},

(I just copied the HTML of a normal Sencha Touch text input)

3. Initialising the auto complete field

You will have to make sure everything is rendered before you try to initialise the auto complete functionality, so add the following painted listener under the config options of the view:

listeners: [
     {
         fn: 'init',
         event: 'painted'
     }
],

and of course add the accompanying function in your view file:

init: function(){
    var me = this;
    var locationInput = document.getElementById('locationField');

    //Create new autocomplete object
    locationComplete = new google.maps.places.Autocomplete(locationInput);

    //Bias to users current location
    this.geolocate();
    var place;

    google.maps.event.addListener(locationComplete, 'place_changed', function() {
        place = locationComplete.getPlace();
        console.log(place.formatted_address); //address
        console.log(place.geometry.location.lat()); //latitude
        console.log(place.geometry.location.lng()); //longitude
    });
},

You will notice a reference to another function here called 'geolocate'. This allows us to bias the place auto complete suggestions based on the current location of the user (assuming they are on a device that supports 'navigator.geolocation'). So if they type a street name they're going to get the street near them, not the one in Italy or Iceland (unless of course that's where they're actually from). Here's the code for the geolocate function, straight out of the documentation:

geolocate: function() {
  if (navigator.geolocation) {
    navigator.geolocation.getCurrentPosition(function(position) {
      var geolocation = new google.maps.LatLng(
          position.coords.latitude, position.coords.longitude);

      locationComplete.setBounds(new google.maps.LatLngBounds(geolocation,
          geolocation));
    });
  }
},

Now if you load up your app you should be able to type in the field you just created and watch the Google Places API do its thing. Amazing.