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"],
strictBounds: false,
};
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: string, countries: string[] | string) {
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",
]);
}
declare global {
interface Window {
initMap: () => void;
}
}
window.initMap = initMap;
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"],
strictBounds: false,
};
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",
]);
}
window.initMap = initMap;
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 {
background-color: #fff;
border: 0;
border-radius: 2px;
box-shadow: 0 1px 4px -1px rgba(0, 0, 0, 0.3);
margin: 10px;
padding: 0 0.5em;
font: 400 18px Roboto, Arial, sans-serif;
overflow: hidden;
font-family: Roboto;
padding: 0;
}
#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
<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 type="module" 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>
<!--
The `defer` attribute causes the script to execute after the full HTML
document has been parsed. For non-blocking uses, avoiding race conditions,
and consistent behavior across browsers, consider loading using Promises. See
https://developers.google.com/maps/documentation/javascript/load-maps-js-api
for more information.
-->
<script
src="https://maps.googleapis.com/maps/api/js?key=AIzaSyB41DRUbKWJHPxaFjMAwdrzWzbVKartNGg&callback=initMap&libraries=places&v=weekly"
defer
></script>
</body>
</html>