Place Autocomplete Restricted to Multiple Countries

This example uses the Place Autocomplete widget to provide a type-ahead search box. The radio buttons allow you to select whether to restrict results to the continental United States, or to include results in the unincorporated organized territories: Puerto Rico, Virgin Islands, Guam and the Northern Mariana Islands.

Read the documentation.

TypeScript

// 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(): void {
  const map = new google.maps.Map(
    document.getElementById("map") as HTMLElement,
    {
      center: { lat: 50.064192, lng: -130.605469 },
      zoom: 3,
    }
  );
  const card = document.getElementById("pac-card") as HTMLElement;
  map.controls[google.maps.ControlPosition.TOP_RIGHT].push(card);
  const center = { lat: 50.064192, lng: -130.605469 };
  // Create a bounding box with sides ~10km away from the center point
  const defaultBounds = {
    north: center.lat + 0.1,
    south: center.lat - 0.1,
    east: center.lng + 0.1,
    west: center.lng - 0.1,
  };
  const input = document.getElementById("pac-input") as HTMLInputElement;
  const options = {
    bounds: defaultBounds,
    componentRestrictions: { country: "us" },
    fields: ["address_components", "geometry", "icon", "name"],
    origin: center,
    strictBounds: false,
    types: ["establishment"],
  };

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

  // Set initial restriction to the greater list of countries.
  autocomplete.setComponentRestrictions({
    country: ["us", "pr", "vi", "gu", "mp"],
  });

  const southwest = { lat: 5.6108, lng: 136.589326 };
  const northeast = { lat: 61.179287, lng: 2.64325 };
  const newBounds = new google.maps.LatLngBounds(southwest, northeast);
  autocomplete.setBounds(newBounds);

  const infowindow = new google.maps.InfoWindow();
  const infowindowContent = document.getElementById(
    "infowindow-content"
  ) as HTMLElement;
  infowindow.setContent(infowindowContent);
  const marker = new google.maps.Marker({
    map,
    anchorPoint: new google.maps.Point(0, -29),
  });

  autocomplete.addListener("place_changed", () => {
    infowindow.close();
    marker.setVisible(false);
    const place = autocomplete.getPlace();

    if (!place.geometry || !place.geometry.location) {
      // 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;
    }

    // If the place has a geometry, then present it on a map.
    if (place.geometry.viewport) {
      map.fitBounds(place.geometry.viewport);
    } else {
      map.setCenter(place.geometry.location);
      map.setZoom(17); // Why 17? Because it looks good.
    }
    marker.setPosition(place.geometry.location);
    marker.setVisible(true);

    let 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);
  });

  // Sets a listener on a given radio button. The radio buttons specify
  // the countries used to restrict the autocomplete search.
  function setupClickListener(id, countries) {
    const radioButton = document.getElementById(id) as HTMLElement;
    radioButton.addEventListener("click", () => {
      autocomplete.setComponentRestrictions({ country: countries });
    });
  }

  setupClickListener("changecountry-usa", "us");
  setupClickListener("changecountry-usa-and-uot", [
    "us",
    "pr",
    "vi",
    "gu",
    "mp",
  ]);
}

JavaScript

// 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() {
  const map = new google.maps.Map(document.getElementById("map"), {
    center: { lat: 50.064192, lng: -130.605469 },
    zoom: 3,
  });
  const card = document.getElementById("pac-card");
  map.controls[google.maps.ControlPosition.TOP_RIGHT].push(card);
  const center = { lat: 50.064192, lng: -130.605469 };
  // Create a bounding box with sides ~10km away from the center point
  const defaultBounds = {
    north: center.lat + 0.1,
    south: center.lat - 0.1,
    east: center.lng + 0.1,
    west: center.lng - 0.1,
  };
  const input = document.getElementById("pac-input");
  const options = {
    bounds: defaultBounds,
    componentRestrictions: { country: "us" },
    fields: ["address_components", "geometry", "icon", "name"],
    origin: center,
    strictBounds: false,
    types: ["establishment"],
  };
  const autocomplete = new google.maps.places.Autocomplete(input, options);
  // Set initial restriction to the greater list of countries.
  autocomplete.setComponentRestrictions({
    country: ["us", "pr", "vi", "gu", "mp"],
  });
  const southwest = { lat: 5.6108, lng: 136.589326 };
  const northeast = { lat: 61.179287, lng: 2.64325 };
  const newBounds = new google.maps.LatLngBounds(southwest, northeast);
  autocomplete.setBounds(newBounds);
  const infowindow = new google.maps.InfoWindow();
  const infowindowContent = document.getElementById("infowindow-content");
  infowindow.setContent(infowindowContent);
  const marker = new google.maps.Marker({
    map,
    anchorPoint: new google.maps.Point(0, -29),
  });
  autocomplete.addListener("place_changed", () => {
    infowindow.close();
    marker.setVisible(false);
    const place = autocomplete.getPlace();

    if (!place.geometry || !place.geometry.location) {
      // 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;
    }

    // If the place has a geometry, then present it on a map.
    if (place.geometry.viewport) {
      map.fitBounds(place.geometry.viewport);
    } else {
      map.setCenter(place.geometry.location);
      map.setZoom(17); // Why 17? Because it looks good.
    }
    marker.setPosition(place.geometry.location);
    marker.setVisible(true);
    let 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);
  });

  // Sets a listener on a given radio button. The radio buttons specify
  // the countries used to restrict the autocomplete search.
  function setupClickListener(id, countries) {
    const radioButton = document.getElementById(id);
    radioButton.addEventListener("click", () => {
      autocomplete.setComponentRestrictions({ country: countries });
    });
  }
  setupClickListener("changecountry-usa", "us");
  setupClickListener("changecountry-usa-and-uot", [
    "us",
    "pr",
    "vi",
    "gu",
    "mp",
  ]);
}

CSS

/* Always set the map height explicitly to define the size of the div
       * element that contains the map. */
#map {
  height: 100%;
}

/* 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;
}

HTML

<!DOCTYPE html>
<html>
  <head>
    <title>Place Autocomplete Restricted to Multiple Countries</title>
    <script src="https://polyfill.io/v3/polyfill.min.js?features=default"></script>
    <link rel="stylesheet" type="text/css" href="./style.css" />
    <script src="./index.js"></script>
  </head>
  <body>
    <div class="pac-card" id="pac-card">
      <div>
        <div id="title">Countries</div>
        <div id="country-selector" class="pac-controls">
          <input type="radio" name="type" id="changecountry-usa" />
          <label for="changecountry-usa">USA</label>

          <input
            type="radio"
            name="type"
            id="changecountry-usa-and-uot"
            checked="checked"
          />
          <label for="changecountry-usa-and-uot"
            >USA and unincorporated organized territories</label
          >
        </div>
      </div>
      <div id="pac-container">
        <input id="pac-input" type="text" placeholder="Enter a location" />
      </div>
    </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>

    <!-- Async script executes immediately and must be after any DOM elements used in callback. -->
    <script
      src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&callback=initMap&libraries=places&v=weekly"
      async
    ></script>
  </body>
</html>

All

<!DOCTYPE html>
<html>
  <head>
    <title>Place Autocomplete Restricted to Multiple Countries</title>
    <script src="https://polyfill.io/v3/polyfill.min.js?features=default"></script>
    <style type="text/css">
      /* Always set the map height explicitly to define the size of the div
       * element that contains the map. */
      #map {
        height: 100%;
      }

      /* 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;
      }
    </style>
    <script>
      // 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() {
        const map = new google.maps.Map(document.getElementById("map"), {
          center: { lat: 50.064192, lng: -130.605469 },
          zoom: 3,
        });
        const card = document.getElementById("pac-card");
        map.controls[google.maps.ControlPosition.TOP_RIGHT].push(card);
        const center = { lat: 50.064192, lng: -130.605469 };
        // Create a bounding box with sides ~10km away from the center point
        const defaultBounds = {
          north: center.lat + 0.1,
          south: center.lat - 0.1,
          east: center.lng + 0.1,
          west: center.lng - 0.1,
        };
        const input = document.getElementById("pac-input");
        const options = {
          bounds: defaultBounds,
          componentRestrictions: { country: "us" },
          fields: ["address_components", "geometry", "icon", "name"],
          origin: center,
          strictBounds: false,
          types: ["establishment"],
        };
        const autocomplete = new google.maps.places.Autocomplete(
          input,
          options
        );
        // Set initial restriction to the greater list of countries.
        autocomplete.setComponentRestrictions({
          country: ["us", "pr", "vi", "gu", "mp"],
        });
        const southwest = { lat: 5.6108, lng: 136.589326 };
        const northeast = { lat: 61.179287, lng: 2.64325 };
        const newBounds = new google.maps.LatLngBounds(southwest, northeast);
        autocomplete.setBounds(newBounds);
        const infowindow = new google.maps.InfoWindow();
        const infowindowContent = document.getElementById("infowindow-content");
        infowindow.setContent(infowindowContent);
        const marker = new google.maps.Marker({
          map,
          anchorPoint: new google.maps.Point(0, -29),
        });
        autocomplete.addListener("place_changed", () => {
          infowindow.close();
          marker.setVisible(false);
          const place = autocomplete.getPlace();

          if (!place.geometry || !place.geometry.location) {
            // 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;
          }

          // If the place has a geometry, then present it on a map.
          if (place.geometry.viewport) {
            map.fitBounds(place.geometry.viewport);
          } else {
            map.setCenter(place.geometry.location);
            map.setZoom(17); // Why 17? Because it looks good.
          }
          marker.setPosition(place.geometry.location);
          marker.setVisible(true);
          let 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);
        });

        // Sets a listener on a given radio button. The radio buttons specify
        // the countries used to restrict the autocomplete search.
        function setupClickListener(id, countries) {
          const radioButton = document.getElementById(id);
          radioButton.addEventListener("click", () => {
            autocomplete.setComponentRestrictions({ country: countries });
          });
        }
        setupClickListener("changecountry-usa", "us");
        setupClickListener("changecountry-usa-and-uot", [
          "us",
          "pr",
          "vi",
          "gu",
          "mp",
        ]);
      }
    </script>
  </head>
  <body>
    <div class="pac-card" id="pac-card">
      <div>
        <div id="title">Countries</div>
        <div id="country-selector" class="pac-controls">
          <input type="radio" name="type" id="changecountry-usa" />
          <label for="changecountry-usa">USA</label>

          <input
            type="radio"
            name="type"
            id="changecountry-usa-and-uot"
            checked="checked"
          />
          <label for="changecountry-usa-and-uot"
            >USA and unincorporated organized territories</label
          >
        </div>
      </div>
      <div id="pac-container">
        <input id="pac-input" type="text" placeholder="Enter a location" />
      </div>
    </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>

    <!-- Async script executes immediately and must be after any DOM elements used in callback. -->
    <script
      src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&callback=initMap&libraries=places&v=weekly"
      async
    ></script>
  </body>
</html>
// 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=AIzaSyB41DRUbKWJHPxaFjMAwdrzWzbVKartNGg&libraries=places"> function initMap() { const map = new google.maps.Map(document.getElementById("map"), { center: { lat: 50.064192, lng: -130.605469 }, zoom: 3, }); const card = document.getElementById("pac-card"); map.controls[google.maps.ControlPosition.TOP_RIGHT].push(card); const center = { lat: 50.064192, lng: -130.605469 }; // Create a bounding box with sides ~10km away from the center point const defaultBounds = { north: center.lat + 0.1, south: center.lat - 0.1, east: center.lng + 0.1, west: center.lng - 0.1, }; const input = document.getElementById("pac-input"); const options = { bounds: defaultBounds, componentRestrictions: { country: "us" }, fields: ["address_components", "geometry", "icon", "name"], origin: center, strictBounds: false, types: ["establishment"], }; const autocomplete = new google.maps.places.Autocomplete(input, options); // Set initial restriction to the greater list of countries. autocomplete.setComponentRestrictions({ country: ["us", "pr", "vi", "gu", "mp"], }); const southwest = { lat: 5.6108, lng: 136.589326 }; const northeast = { lat: 61.179287, lng: 2.64325 }; const newBounds = new google.maps.LatLngBounds(southwest, northeast); autocomplete.setBounds(newBounds); const infowindow = new google.maps.InfoWindow(); const infowindowContent = document.getElementById("infowindow-content"); infowindow.setContent(infowindowContent); const marker = new google.maps.Marker({ map, anchorPoint: new google.maps.Point(0, -29), }); autocomplete.addListener("place_changed", () => { infowindow.close(); marker.setVisible(false); const place = autocomplete.getPlace(); if (!place.geometry || !place.geometry.location) { // 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; } // If the place has a geometry, then present it on a map. if (place.geometry.viewport) { map.fitBounds(place.geometry.viewport); } else { map.setCenter(place.geometry.location); map.setZoom(17); // Why 17? Because it looks good. } marker.setPosition(place.geometry.location); marker.setVisible(true); let 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); }); // Sets a listener on a given radio button. The radio buttons specify // the countries used to restrict the autocomplete search. function setupClickListener(id, countries) { const radioButton = document.getElementById(id); radioButton.addEventListener("click", () => { autocomplete.setComponentRestrictions({ country: countries }); }); } setupClickListener("changecountry-usa", "us"); setupClickListener("changecountry-usa-and-uot", [ "us", "pr", "vi", "gu", "mp", ]); }
/* Always set the map height explicitly to define the size of the div * element that contains the map. */ #map { height: 100%; } /* 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; }
<!DOCTYPE html> <html> <head> <title>Place Autocomplete Restricted to Multiple Countries</title> <script src="https://polyfill.io/v3/polyfill.min.js?features=default"></script> <!-- jsFiddle will insert css and js --> </head> <body> <div class="pac-card" id="pac-card"> <div> <div id="title">Countries</div> <div id="country-selector" class="pac-controls"> <input type="radio" name="type" id="changecountry-usa" /> <label for="changecountry-usa">USA</label> <input type="radio" name="type" id="changecountry-usa-and-uot" checked="checked" /> <label for="changecountry-usa-and-uot" >USA and unincorporated organized territories</label > </div> </div> <div id="pac-container"> <input id="pac-input" type="text" placeholder="Enter a location" /> </div> </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> <!-- Async script executes immediately and must be after any DOM elements used in callback. --> <script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyB41DRUbKWJHPxaFjMAwdrzWzbVKartNGg&callback=initMap&libraries=places&v=weekly" async ></script> </body> </html>