Welcome to the experimental release for the new improved Place Autocomplete. Autocomplete is a feature of the Places library in the Maps JavaScript API. You can use autocomplete to give your applications the type-ahead-search behavior of the Google Maps search field. The autocomplete service can match on full words and substrings, resolving place names, addresses, and plus codes. Applications can therefore send queries as the user types, to provide on-the-fly place predictions.
Prerequisites
Welcome to the Place Autocomplete (New) (Experimental). To use Text Search (Preview),
you must enable "Places API" on your Google Cloud project, and specify the alpha channel (v: "alpha"
)
in your bootstrap loader. See Get started
for details.
What's new
Place Autocomplete (Experimental) has been improved in the following ways:
- The Autocomplete widget UI supports regional localization (including RTL languages), for the text input placeholder, predictions list logo, and the place predictions.
- Enhanced accessibility, including support for screen readers and keyboard interaction.
- The Autocomplete widget returns the new Place class to simplify handling of the returned object.
- Better support for mobile devices and small screens.
- Better performance and improved graphical appearance.
Add an Autocomplete widget
You can add an Autocomplete widget to a web page or a Google map. The Autocomplete widget creates
a text input field, supplies place predictions in a UI pick list, and returns place details in
response to a user click via the gmp-placeselect
listener. This section shows you
how to add an autocomplete widget to a web page, or a Google map.
Add an Autocomplete widget to a web page
To add the Autocomplete widget to a web page, create a new input
element, then use
that to create a new google.maps.places.PlaceAutocompleteElement
, and append it to
the page as shown in the following example:
TypeScript
// Request needed libraries. //@ts-ignore const [{ Map }] = await Promise.all([ google.maps.importLibrary("places"), ]); // Create the input HTML element, and append it. const input = document.createElement('input'); const pac = new google.maps.places.PlaceAutocompleteElement({ inputElement: input }); document.body.appendChild(pac.element as HTMLElement);
JavaScript
// Request needed libraries. //@ts-ignore const [{ Map }] = await Promise.all([google.maps.importLibrary("places")]); // Create the input HTML element, and append it. const input = document.createElement("input"); const pac = new google.maps.places.PlaceAutocompleteElement({ inputElement: input, }); document.body.appendChild(pac.element);
Add an Autocomplete widget to a map
To add an Autocomplete widget to a map, create a new input
element, use that to
create a new google.maps.places.PlaceAutocompleteElement
instance, append the
PlaceAutocompleteElement
to a div
, and push it onto the map as a custom
control, as shown in the following example:
TypeScript
// Create the input HTML element, and add it to the map as a custom control. const input = document.createElement('input'); input.id = 'pac-input'; //@ts-ignore const pac = new google.maps.places.PlaceAutocompleteElement({ inputElement: input }); const card = document.getElementById('pac-card') as HTMLElement; card.appendChild(pac.element as HTMLElement); map.controls[google.maps.ControlPosition.TOP_LEFT].push(card);
JavaScript
// Create the input HTML element, and add it to the map as a custom control. const input = document.createElement("input"); input.id = "pac-input"; //@ts-ignore const pac = new google.maps.places.PlaceAutocompleteElement({ inputElement: input, }); const card = document.getElementById("pac-card"); card.appendChild(pac.element); map.controls[google.maps.ControlPosition.TOP_LEFT].push(card);
Constrain Autocomplete predictions
By default, Place Autocomplete presents all place types, biased for predictions near the user's location, and fetches all available data fields for the user's selected place. Set Place Autocomplete options to present more relevant predictions, by restricting or biasing results.
Restricting results causes the Autocomplete widget ignore any results that are outside of the restriction area. A common practice is to restrict results to the map bounds. Biasing results makes the Autocomplete widget show results within the specified area, but some matches may be outside of that area.
Restrict place search by country
To restrict place search to one or more specific countries, use the componentRestrictions
property to specify the country code(s) as shown in the following snippet:
const pac = new google.maps.places.PlaceAutocompleteElement({ inputElement: input, componentRestrictions: {country: ['us', 'au']}, });
Restrict place search to map bounds
To restrict place search to a map's bounds, use the locationRestrictions
property to add the bounds, as shown in the following snippet:
const pac = new google.maps.places.PlaceAutocompleteElement({ inputElement: input, locationRestriction: map.getBounds(), });
When restricting to map bounds, be sure to add a listener to update the bounds when they change:
map.addListener('bounds_changed', () => { autocomplete.locationRestriction = map.getBounds(); });
To remove the locationRestriction
, set it to null
.
Bias place search results
Bias place search results to a circle area by using the locationBias
property, and
passing a radius, as shown here:
const autocomplete = new google.maps.places.PlaceAutocompleteElement({ inputElement: input, locationBias: {radius: 100, center: {lat: 50.064192, lng: -130.605469}}, });
To remove the locationBias
, set it to null
.
Restrict place search results to certain types
Restrict place search results to certain types of places by using the types
property, and specifying one or more types, as shown here:
const autocomplete = new google.maps.places.PlaceAutocompleteElement({ inputElement: input, types: ['establishment'], });
For a complete list of supported types, see Table 3: Types supported in place autocomplete requests.
Get place details
To get place details for the selected place, add a gmp-place-select
listener to
the PlaceAutocompleteElement
, as shown in the following example:
TypeScript
// Add the gmp-placeselect listener, and display the results. pac.addListener('gmp-placeselect', async ({ place }) => { await place.fetchFields({ fields: ['displayName', 'formattedAddress', 'location'] }); selectedPlaceTitle.textContent = 'Selected Place:'; selectedPlaceInfo.textContent = JSON.stringify( place.toJSON(), /* replacer */ null, /* space */ 2); });
JavaScript
// Add the gmp-placeselect listener, and display the results. pac.addListener("gmp-placeselect", async ({ place }) => { await place.fetchFields({ fields: ["displayName", "formattedAddress", "location"], }); selectedPlaceTitle.textContent = "Selected Place:"; selectedPlaceInfo.textContent = JSON.stringify( place.toJSON(), /* replacer */ null, /* space */ 2 ); });
In the preceding example, the event listener returns an object of Place class.
Call place.fetchFields()
to get the Place Details data fields
needed for your application.
The listener in the next example requests place information and displays it on a map.
TypeScript
// Add the gmp-placeselect listener, and display the results on the map. pac.addListener('gmp-placeselect', async ({ place }) => { await place.fetchFields({ fields: ['displayName', 'formattedAddress', 'location'] }); // If the place has a geometry, then present it on a map. if (place.viewport) { map.fitBounds(place.viewport); } else { map.setCenter(place.location); map.setZoom(17); } let content = '<div id="infowindow-content">' + '<span id="place-displayname" class="title">' + place.displayName + '</span><br />' + '<span id="place-address">' + place.formattedAddress + '</span>' + '</div>'; updateInfoWindow(content, place.location); marker.position = place.location; });
JavaScript
// Add the gmp-placeselect listener, and display the results on the map. pac.addListener("gmp-placeselect", async ({ place }) => { await place.fetchFields({ fields: ["displayName", "formattedAddress", "location"], }); // If the place has a geometry, then present it on a map. if (place.viewport) { map.fitBounds(place.viewport); } else { map.setCenter(place.location); map.setZoom(17); } let content = '<div id="infowindow-content">' + '<span id="place-displayname" class="title">' + place.displayName + "</span><br />" + '<span id="place-address">' + place.formattedAddress + "</span>" + "</div>"; updateInfoWindow(content, place.location); marker.position = place.location; });
Get geocoding results for the selected place
To get geocoding results for the selected place, use google.maps.Geocoder
to get
the location, as shown in the following snippet:
const map = new google.maps.Map(document.getElementById('map'), { center: {lat: 50.064192, lng: -130.605469}, zoom: 3, }); const marker = new google.maps.Marker({map}); const inputElement = document.getElementById('pac-input'); const autocomplete = new google.maps.places.PlaceAutocompleteElement({inputElement}); const geocoder = new google.maps.Geocoder(); autocomplete.addListener('gmp-placeselect', async ({prediction: place}) => { const results = await geocoder.geocode({place.id}); marker.setPlace({ placeId: place.id, location: results[0].geometry.location, }); });
Example maps
This section contains the complete code for the example maps featured on this page.
Autocomplete element
This example adds an Autocomplete widget to a web page, and displays the results for each selected place.
TypeScript
async function initMap(): Promise<void> { // Request needed libraries. //@ts-ignore const [{ Map }] = await Promise.all([ google.maps.importLibrary("places"), ]); // Create the input HTML element, and append it. const input = document.createElement('input'); const pac = new google.maps.places.PlaceAutocompleteElement({ inputElement: input }); document.body.appendChild(pac.element as HTMLElement); // Inject HTML UI. const selectedPlaceTitle = document.createElement('p'); selectedPlaceTitle.textContent = ''; document.body.appendChild(selectedPlaceTitle); const selectedPlaceInfo = document.createElement('pre'); selectedPlaceInfo.textContent = ''; document.body.appendChild(selectedPlaceInfo); // Add the gmp-placeselect listener, and display the results. pac.addListener('gmp-placeselect', async ({ place }) => { await place.fetchFields({ fields: ['displayName', 'formattedAddress', 'location'] }); selectedPlaceTitle.textContent = 'Selected Place:'; selectedPlaceInfo.textContent = JSON.stringify( place.toJSON(), /* replacer */ null, /* space */ 2); }); } initMap();
JavaScript
async function initMap() { // Request needed libraries. //@ts-ignore const [{ Map }] = await Promise.all([google.maps.importLibrary("places")]); // Create the input HTML element, and append it. const input = document.createElement("input"); const pac = new google.maps.places.PlaceAutocompleteElement({ inputElement: input, }); document.body.appendChild(pac.element); // Inject HTML UI. const selectedPlaceTitle = document.createElement("p"); selectedPlaceTitle.textContent = ""; document.body.appendChild(selectedPlaceTitle); const selectedPlaceInfo = document.createElement("pre"); selectedPlaceInfo.textContent = ""; document.body.appendChild(selectedPlaceInfo); // Add the gmp-placeselect listener, and display the results. pac.addListener("gmp-placeselect", async ({ place }) => { await place.fetchFields({ fields: ["displayName", "formattedAddress", "location"], }); selectedPlaceTitle.textContent = "Selected Place:"; selectedPlaceInfo.textContent = JSON.stringify( place.toJSON(), /* replacer */ null, /* space */ 2 ); }); } 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; } p { font-family: Roboto, sans-serif; font-weight: bold; } [class$=api-load-alpha-banner] { display: none; }
HTML
<html> <head> <title>Place Autocomplete element</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> <p style="font-family: roboto, sans-serif">Search for a place here:</p> <!-- prettier-ignore --> <script>(g=>{var h,a,k,p="The Google Maps JavaScript API",c="google",l="importLibrary",q="__ib__",m=document,b=window;b=b[c]||(b[c]={});var d=b.maps||(b.maps={}),r=new Set,e=new URLSearchParams,u=()=>h||(h=new Promise(async(f,n)=>{await (a=m.createElement("script"));e.set("libraries",[...r]+"");for(k in g)e.set(k.replace(/[A-Z]/g,t=>"_"+t[0].toLowerCase()),g[k]);e.set("callback",c+".maps."+q);a.src=`https://maps.${c}apis.com/maps/api/js?`+e;d[q]=f;a.onerror=()=>h=n(Error(p+" could not load."));a.nonce=m.querySelector("script[nonce]")?.nonce||"";m.head.append(a)}));d[l]?console.warn(p+" only loads once. Ignoring:",g):d[l]=(f,...n)=>r.add(f)&&u().then(()=>d[l](f,...n))}) ({key: "AIzaSyB41DRUbKWJHPxaFjMAwdrzWzbVKartNGg", v: "alpha"});</script> </body> </html>
Try Sample
Autocomplete map
This example shows you how to add an Autocomplete widget to a Google map.
TypeScript
let map: google.maps.Map; let marker: google.maps.marker.AdvancedMarkerElement; let infoWindow: google.maps.InfoWindow; async function initMap(): Promise<void> { // Request needed libraries. //@ts-ignore const [{ Map }, { AdvancedMarkerElement }] = await Promise.all([ google.maps.importLibrary("marker"), google.maps.importLibrary("places") ]); // Initialize the map. map = new google.maps.Map(document.getElementById('map') as HTMLElement, { center: { lat: 40.749933, lng: -73.98633 }, zoom: 13, mapId: '4504f8b37365c3d0', mapTypeControl: false, }); // Create the input HTML element, and add it to the map as a custom control. const input = document.createElement('input'); input.id = 'pac-input'; //@ts-ignore const pac = new google.maps.places.PlaceAutocompleteElement({ inputElement: input }); const card = document.getElementById('pac-card') as HTMLElement; card.appendChild(pac.element as HTMLElement); map.controls[google.maps.ControlPosition.TOP_LEFT].push(card); // Create the marker and infowindow marker = new google.maps.marker.AdvancedMarkerElement({ map, }); infoWindow = new google.maps.InfoWindow({}); // Add the gmp-placeselect listener, and display the results on the map. pac.addListener('gmp-placeselect', async ({ place }) => { await place.fetchFields({ fields: ['displayName', 'formattedAddress', 'location'] }); // If the place has a geometry, then present it on a map. if (place.viewport) { map.fitBounds(place.viewport); } else { map.setCenter(place.location); map.setZoom(17); } let content = '<div id="infowindow-content">' + '<span id="place-displayname" class="title">' + place.displayName + '</span><br />' + '<span id="place-address">' + place.formattedAddress + '</span>' + '</div>'; updateInfoWindow(content, place.location); marker.position = place.location; }); } // Helper function to create an info window. function updateInfoWindow(content, center) { infoWindow.setContent(content); infoWindow.setPosition(center); infoWindow.open({ map, anchor: marker, shouldFocus: false, }); } initMap();
JavaScript
let map; let marker; let infoWindow; async function initMap() { // Request needed libraries. //@ts-ignore const [{ Map }, { AdvancedMarkerElement }] = await Promise.all([ google.maps.importLibrary("marker"), google.maps.importLibrary("places"), ]); // Initialize the map. map = new google.maps.Map(document.getElementById("map"), { center: { lat: 40.749933, lng: -73.98633 }, zoom: 13, mapId: "4504f8b37365c3d0", mapTypeControl: false, }); // Create the input HTML element, and add it to the map as a custom control. const input = document.createElement("input"); input.id = "pac-input"; //@ts-ignore const pac = new google.maps.places.PlaceAutocompleteElement({ inputElement: input, }); const card = document.getElementById("pac-card"); card.appendChild(pac.element); map.controls[google.maps.ControlPosition.TOP_LEFT].push(card); // Create the marker and infowindow marker = new google.maps.marker.AdvancedMarkerElement({ map, }); infoWindow = new google.maps.InfoWindow({}); // Add the gmp-placeselect listener, and display the results on the map. pac.addListener("gmp-placeselect", async ({ place }) => { await place.fetchFields({ fields: ["displayName", "formattedAddress", "location"], }); // If the place has a geometry, then present it on a map. if (place.viewport) { map.fitBounds(place.viewport); } else { map.setCenter(place.location); map.setZoom(17); } let content = '<div id="infowindow-content">' + '<span id="place-displayname" class="title">' + place.displayName + "</span><br />" + '<span id="place-address">' + place.formattedAddress + "</span>" + "</div>"; updateInfoWindow(content, place.location); marker.position = place.location; }); } // Helper function to create an info window. function updateInfoWindow(content, center) { infoWindow.setContent(content); infoWindow.setPosition(center); infoWindow.open({ map, anchor: marker, shouldFocus: false, }); } 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; } #map_canvas { flex: 1; } #pac-card { background-color: #fff; border-radius: 5px; box-shadow: rgba(0, 0, 0, 0.35) 0px 5px 15px; margin: 10px; padding: 5px; font-family: Roboto, sans-serif; font-size: large; font-weight: bold; } #pac-input { width: 250px; } #infowindow-content .title { font-weight: bold; } #map #infowindow-content { display: inline; } [class$=api-load-alpha-banner] { display: none; }
HTML
<html> <head> <title>Place Autocomplete map</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"> <p>Search for a place here:</p> </div> <div id="map"></div> <!-- prettier-ignore --> <script>(g=>{var h,a,k,p="The Google Maps JavaScript API",c="google",l="importLibrary",q="__ib__",m=document,b=window;b=b[c]||(b[c]={});var d=b.maps||(b.maps={}),r=new Set,e=new URLSearchParams,u=()=>h||(h=new Promise(async(f,n)=>{await (a=m.createElement("script"));e.set("libraries",[...r]+"");for(k in g)e.set(k.replace(/[A-Z]/g,t=>"_"+t[0].toLowerCase()),g[k]);e.set("callback",c+".maps."+q);a.src=`https://maps.${c}apis.com/maps/api/js?`+e;d[q]=f;a.onerror=()=>h=n(Error(p+" could not load."));a.nonce=m.querySelector("script[nonce]")?.nonce||"";m.head.append(a)}));d[l]?console.warn(p+" only loads once. Ignoring:",g):d[l]=(f,...n)=>r.add(f)&&u().then(()=>d[l](f,...n))}) ({key: "AIzaSyB41DRUbKWJHPxaFjMAwdrzWzbVKartNGg", v: "alpha"});</script> </body> </html>