'Google maps API autocomplete.getPlace() inconsistently returns geometry

I'm using GoogleMaps Autocomplete in an AngularJS application and when I call...

autocomplete.getPlace(); 

half the time when i try to use place it says geometry is null and half the time it works...

Cant seem to figure it out...my only idea is that my code is moving on before getPlace() returns but i'm not sure how to wait for it to get done?

My library include...

 <script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?key=MyKey&libraries=imagery,places,geometry">
 </script>    

Creating autocomplete...

this.autocomplete = null;
$scope.initAutoComplete = function() {
  // Create the autocomplete object, restricting the search to geographical
  // location types.

  webMapValues.autocomplete = new google.maps.places.Autocomplete( /** @type {!HTMLInputElement} */ (document.getElementById('autocomplete')), {
    types: ['geocode']
  });

  // When the user selects an address from the dropdown, populate the address
  // fields in the form.
  webMapValues.autocomplete.addListener('place_changed', rcisMapService.dropPin);
};

My DropPin function...

mapSVC.dropPin = function() {

  var place = webMapValues.autocomplete.getPlace();

  webMapValues.mapObj.getView().setCenter(ol.proj.transform([place.geometry.location.lng(), place.geometry.location.lat()], 'EPSG:4326', 'EPSG:3857'));
  webMapValues.mapObj.getView().setZoom(17);
  webMapValues.marker = new google.maps.Marker({
    map: webMapValues.gmapObj,
    anchorPoint: new google.maps.Point(0, -29)
  });
  webMapValues.marker.setIcon( /** @type {google.maps.Icon} */ ({
    url: place.icon,
    size: new google.maps.Size(71, 71),
    origin: new google.maps.Point(0, 0),
    anchor: new google.maps.Point(17, 34),
    scaledSize: new google.maps.Size(35, 35)
  }));
  webMapValues.marker.setPosition(place.geometry.location);
  webMapValues.marker.setVisible(true);
};

autocomplete is working great, but when I call "getPlace()"
half the time...

"geometry" in the below line is not defined. place.geometry.location.lng()

Any help you can provide is greatly appreciated!!



Solution 1:[1]

Okay so this was a really hard problem to solve because the cause wasn't apparent...autoComplete.getPlace() would just return 'undefined' the first time I called it on each new address.

I'm still not sure why that's happening and neither is Google because I used our google cloud support to see if they had any ideas, it turns out they didn't.

Here's the solution I came up with... essentially in the "Creating AutoComplete" section of my code above I abandon autocomplete and replaced it with google.maps.places.

Be sure to add "places" in your call to the google API...

<script async defer src="https://maps.googleapis.com/maps/api/js?key=YourKey&libraries=imagery,places">

This is what it looks like...

          $scope.initAutoComplete = function(){

                    //get textbox used for address or place search
                    var input = document.getElementById('autocomplete');

                    //create google places variable and bind input to it.
                    var searchBox = new google.maps.places.SearchBox(input);


                    // When the user selects an address from the dropdown, 
                      trigger function
                    searchBox.addListener('places_changed', function () {
                        //calling "getPlaces" instead of get place()

                        var place = searchBox.getPlaces();

                        //passing place to my dropPin service
                        rcisMapService.dropPin(place);
                    });
                };

I also added class="controls" to the used for address/place search

This solution consistently returns every time.

Solution 2:[2]

I had this same issue with a Vue.js app. The first attempt to getPlace() returned undefined and the second would return the google place object as expected.

The issue was actually attempting to v-model the same data attribute I was setting equal to new google.maps.places.Autocomplete(input).

originally I was doing this:

    const input = this.$refs.autocomplete;
    const options = {
      types: ['address'],
    };

    this.autocomplete = new google.maps.places.Autocomplete(
      input,
      options,
    );

    this.autocomplete.setFields(['address_components', 'name']);

    this.autocomplete.addListener('place_changed', () => {
      let place = this.autocomplete.getPlace();
      console.log(place, 'place');
    });

but what wound up working for me was:

const input = this.$refs.autocomplete;
const options = {
  types: ['address'],
};

let auto_complete = new google.maps.places.Autocomplete(
  input,
  options,
);

auto_complete.setFields(['address_components', 'name']);

auto_complete.addListener('place_changed', () => {
  this.autocomplete = auto_complete.getPlace();
  console.log(this.autocomplete, 'place');
});

with this being the data I was originally trying to set/model:

data() {
  return {
    autocomplete: '',
  };
}

and this being the template:

<input
  v-model="location"
  ref="autocomplete"
  type="text"
/>

resources: https://medium.com/dailyjs/google-places-autocomplete-in-vue-js-350aa934b18d

https://developers.google.com/maps/documentation/javascript/examples/places-autocomplete

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Fabio Zanchi