Search code examples
javascriptgoogle-mapsgoogle-maps-api-3boundsgoogle-places-autocomplete

Can I get a only Dubai city address from Google Maps autocomplete?


I tried this, but it also display the Abu Dhabi location which is out of Dubai. But I want the address in the Dubai area only.

var defaultBounds = new google.maps.LatLngBounds(
    new google.maps.LatLng(25.1851804, 55.2780796) // Dubai area
);
var options = {
    bounds: defaultBounds,
    types: ['establishment'],
    componentRestrictions: { country: 'AE' }
};
var autocomplete = new google.maps.places.Autocomplete(input, options);

Solution

  • The only real option with Autocomplete is to use componentRestrictions to the country (as you are doing), then use strictBounds.

    For the bounds of Dubai, the geocoder returns bounds and viewport of: { north:25.3585607, east:55.5650393, south:24.7921359, west:54.8904543} (the autocomplete API returns a viewport of the same, in place.geometry.viewport).

    Bounds from Google Geocoder (square) vs. Bounds from GADM (not square): bounds of Dubai from Google's Geocoder vs. from GADM

    proof of concept fiddle

    screenshot of result

    code snippet:

    // This example requires the Places library. Include the libraries=places
    // parameter when you first load the API. For example:
    // <script src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&libraries=places">
    
    function initMap() {
      var map = new google.maps.Map(document.getElementById('map'), {
        center: {
          lat: -33.8688,
          lng: 151.2195
        },
        zoom: 13
      });
      var input = document.getElementById('pac-input');
      var dubaiBounds = {
        north: 25.3585607,
        east: 55.5650393,
        south: 24.7921359,
        west: 54.8904543
      };
      map.fitBounds(dubaiBounds);
      var rect = new google.maps.Rectangle({
        map: map,
        bounds: dubaiBounds
      })
    
      var options = {
        bounds: dubaiBounds,
        types: ['establishment'],
        componentRestrictions: {
          country: 'AE'
        },
        strictBounds: true
      };
      var autocomplete = new google.maps.places.Autocomplete(input, options);
      /// show on map
      autocomplete.bindTo('bounds', map);
    
      // Set the data fields to return when the user selects a place.
      autocomplete.setFields(
        ['address_components', 'geometry', 'icon', 'name']);
    
      var infowindow = new google.maps.InfoWindow();
      var infowindowContent = document.getElementById('infowindow-content');
      infowindow.setContent(infowindowContent);
      var marker = new google.maps.Marker({
        map: map,
        anchorPoint: new google.maps.Point(0, -29)
      });
      autocomplete.addListener('place_changed', function() {
        infowindow.close();
        marker.setVisible(false);
        var place = autocomplete.getPlace();
        if (!place.geometry) {
          // User entered the name of a Place that was not suggested and
          // pressed the Enter key, or the Place Details request failed.
          window.alert("No details available for input: '" + place.name + "'");
          return;
        }
        marker.setPosition(place.geometry.location);
        marker.setVisible(true);
    
        var address = '';
        if (place.address_components) {
          address = [
            (place.address_components[0] && place.address_components[0].short_name || ''),
            (place.address_components[1] && place.address_components[1].short_name || ''),
            (place.address_components[2] && place.address_components[2].short_name || '')
          ].join(' ');
        }
    
        infowindowContent.children['place-icon'].src = place.icon;
        infowindowContent.children['place-name'].textContent = place.name;
        infowindowContent.children['place-address'].textContent = address;
        infowindow.open(map, marker);
      });
    
    }
    /* Always set the map height explicitly to define the size of the div
     * element that contains the map. */
    
    #map {
      height: 80%;
    }
    
    
    /* Optional: Makes the sample page fill the window. */
    
    html,
    body {
      height: 100%;
      margin: 0;
      padding: 0;
    }
    
    #description {
      font-family: Roboto;
      font-size: 15px;
      font-weight: 300;
    }
    
    #infowindow-content .title {
      font-weight: bold;
    }
    
    #infowindow-content {
      display: none;
    }
    
    #map #infowindow-content {
      display: inline;
    }
    
    .pac-card {
      margin: 10px 10px 0 0;
      border-radius: 2px 0 0 2px;
      box-sizing: border-box;
      -moz-box-sizing: border-box;
      outline: none;
      box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3);
      background-color: #fff;
      font-family: Roboto;
    }
    
    #pac-container {
      padding-bottom: 12px;
      margin-right: 12px;
    }
    
    .pac-controls {
      display: inline-block;
      padding: 5px 11px;
    }
    
    .pac-controls label {
      font-family: Roboto;
      font-size: 13px;
      font-weight: 300;
    }
    
    #pac-input {
      background-color: #fff;
      font-family: Roboto;
      font-size: 15px;
      font-weight: 300;
      margin-left: 12px;
      padding: 0 11px 0 13px;
      text-overflow: ellipsis;
      width: 400px;
    }
    
    #pac-input:focus {
      border-color: #4d90fe;
    }
    
    #title {
      color: #fff;
      background-color: #4d90fe;
      font-size: 25px;
      font-weight: 500;
      padding: 6px 12px;
    }
    <div id="pac-container">
      <input id="pac-input" type="text" placeholder="Enter a location">
    </div>
    <div id="map"></div>
    <div id="infowindow-content">
      <img src="" width="16" height="16" id="place-icon">
      <span id="place-name" class="title"></span><br>
      <span id="place-address"></span>
    </div>
    <!-- Replace the value of the key parameter with your own API key. -->
    <script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk&libraries=places&callback=initMap" async defer></script>