Objective
Learn how to integrate the Place Search Element with Google Maps to help users to find places using nearby search or text search, enhancing their ability to explore points of interest. Use the Place Details Compact Element to provide more details about the places surfaced in your application.
What is the Place Search Element?
The Place Search Element is part of the Places UI Kit in the Maps JavaScript API. It's a HTML element that renders the results of a place search directly in a list format within your application. This element simplifies the process of displaying places found using a Nearby Search or a Text Search, providing a seamless user experience for place discovery. When a user selects a place from the list, you can display its details on the map, often using an Info Window and the Place Details Element.
Visualize place discovery
The following image shows an example of the Place Search Element in action. On the left, a list of restaurants is displayed (the Place Search Element). When a restaurant is selected, its details appear in an Info Window on the map, and the map centers on its location.
Use Cases for Place Discovery
Integrating the Place Search Element can enhance various applications across different industries:
- Travel and Tourism: Allow tourists to search for attractions, hotels, or specific types of cuisine in an area.
- Real Estate: Enable potential buyers or renters to find nearby schools, supermarkets, or public transport options.
- Logistics and Services: Assist drivers in finding EV charging stations, gas stations, or specific service centers.
Solution Workflow: Implementing Place Discovery
This section walks you through the steps to integrate the Place Search Element for discovering places on a map, including code snippets for interacting with the Places UI Kit. We'll cover initializing the map, and implementing both Nearby Search and Text Search functionalities. Finally, we'll use the Place Details element to show more details about a particular place, on click of its pin on the map.
Prerequisites
Familiarity with the following documentation is recommended:
- Place Search Element - Used to expose places using either Nearby Search or Text Search
- Place Details Element - Used to display details of an individual place
- Maps JavaScript API - Used to show a map on your page, and to import Places UI Kit
Enable Maps JavaScript API and Places UI Kit on your project.
Verify you have loaded the Maps JavaScript API and imported the required libraries before getting started. This document also assumes a working knowledge of web development, including HTML, CSS, and JavaScript.
Add a map to the page
The first step is to add a map to your page. This map will be used to display Place Search Element results as selectable pins.
There are two ways to add a map to a page:
- Using a
gmp-map
HTML web component. - Using JavaScript.
The code snippets on this page were generated using a JavaScript map.
The map can either be centered on a location you would like the user to search around, such as a hotel, or initialized to ask for the user's current location to center the map. For the purposes of this document, we will be using a fixed location to anchor the search.
If you are visualizing places nearby a fixed location, such as a hotel, place a marker on the map to represent this place. For example:
The map is centered on San Francisco, with a blue pin to represent the place we
are searching nearby. The pin color has been customized using
PinElement
.
The Map Type control has been hidden
from the UI.
Set up Place Search Element
Now, we can set up the HTML and CSS to display the Place Search Element. For this example, we are going to float the element over the left side of the map, but it's recommended to try different layouts to suit your application.
Within your HTML code, create a div
that will hold the Place Search Element.
Within this, initialize an empty
gmp-place-list
.
Use the selectable
attribute with gmp-place-list to
enable click events on
the element.
<gmp-place-list selectable></gmp-place-list>
At this stage, use
configureFromSearchNearbyRequest
to search for a Place
Type, to test that results
are correctly displayed.
Use JavaScript to configure the Place Search Element to show the results of a
place search. Initialize a Circle to use as the locationRestriction
, using a
center point, and an appropriate radius. For this example, the element is
configured to search for a place type of restaurant
, and the marker position
set up in the previous step is used as the circle center point.
The code snippet for this is as follows:
const placeListElement = document.querySelector("gmp-place-list");
const circleRestriction = new Circle({
center: marker.position,
radius: 500
});
placeListElement.configureFromSearchNearbyRequest({
locationRestriction: circleRestriction,
includedPrimaryTypes: ['restaurant'],
});
An example of how the application could look at this stage is as follows:
Allow user to search
The Place Search Element allows two search options:
configureFromSearchNearbyRequest
- render search results from a Places Nearby Search, using Place Types.configureFromSearchByTextRequest
- render search results from a Places Text Search, using a free text input such as "Sushi in San Francisco".
This section describes implementing both methods.
Nearby search
Implement a UI element to allow the user to choose which Place
Type the Place Search
Element will display. It's recommended to choose a subset of these types, to
suit your use case. For example, if you're developing an application to show
tourists what's nearby a hotel, you might choose: bakery
, coffee_shop
,
museum
, restaurant
, and tourist_attraction
. Choose the selection method
that works best for your application, for example, a drop-down list populated
with a selection of place types.
Create a JavaScript listener to handle the change event on your Place Type
selection UI. Configure the listener to call a function to update the Place
Search Element based on the place type selected, using
configureFromSearchNearbyRequest
.
An example of updating the Place Search Element using a function is as follows:
// Function to update the place search
function updatePlaceList() {
const selectedType = placeTypeSelect.value;
if (!selectedType) {
console.warn("No place type selected.");
// Clear results or handle as needed
placeListElement.requestedResultTypes = [];
return;
}
placeListElement.configureFromSearchNearbyRequest({
locationRestriction: searchCircle,
maxResultCount: 8,
includedPrimaryTypes: [selectedType],
});
}
The same circle locationRestriction
set up in the previous step is used. The
includedPrimaryTypes
parameter is set based on the value selected in the UI.
An optional maxResultCount
has also been set, to restrict the number of
results returned and displayed in the Place Search Element.
Text Search
Add a text input with a button for your users to enter their text search. Create
a JavaScript listener to handle the click
event on the button, and configure
the Place Search Element to search using the entered search string, using
configureFromSearchByTextRequest
.
const textSearchInput = document.getElementById('textSearchInput');
const textSearchButton = document.getElementById('textSearchButton');
textSearchButton.addEventListener('click', performTextSearch);
function performTextSearch() {
const query = textSearchInput.value.trim();
if (!query) {
console.log("Search query is empty.");
return;
}
placeListElement.configureFromSearchByTextRequest({
textQuery: query,
locationRestriction: map.getBounds(),
maxResultCount: 8,
});
}
For this example, an optional locationRestriction
is set using the current
bounds of the map. The search query is passed using the textQuery
parameter.
An optional maxResultCount
has also been set, to restrict the number of
results returned and displayed in the Place Search Element.
Display Place Pins and Details
Now the application can perform a place search and populate the element. In the next step we will enhance its functionality by:
- Displaying pins on the map for each place populated in the Place Search Element.
- Allowing a user to either click a pin or the place within the Place Search Element, to show more details about that particular place.
The principle of this step will be the same whether the application is using
configureFromSearchNearbyRequest
or configureFromSearchByTextRequest
. For
this example, we will use configureFromSearchNearbyRequest
.
Add a global variable to your JavaScript code to store the place markers. This will allow you to remove them when the search changes, and handle click events to display place details.
let markers = {};
Add a function to:
- Remove existing place markers.
- Loop though the Place Search Element results and add a marker for each one.
- Set the bounds of the map so all markers are visible.
async function addMarkers() {
const { LatLngBounds } = await google.maps.importLibrary("core");
const bounds = new LatLngBounds();
if (placeListElement.places.length > 0) {
// Remove existing markers
for (m in markers) {
markers[m].map = null;
}
markers = {};
// Loop through each place in the Place Search Element
// Add a marker for each place
placeListElement.places.forEach((place) => {
let marker = new AdvancedMarkerElement({
map: map,
position: place.location,
});
markers[place.id] = marker;
bounds.extend(place.location);
marker.collisionBehavior = google.maps.CollisionBehavior.REQUIRED_AND_HIDES_OPTIONAL;
// Position the map to display all markers with the bounds
map.setCenter(bounds.getCenter());
map.fitBounds(bounds);
});
}
}
Finally, once the configureFromSearchNearbyRequest
promise successfully
resolves, call the new addMarkers()
function, as so:
placeListElement.configureFromSearchNearbyRequest({
locationRestriction: searchCircle,
maxResultCount: 8,
includedPrimaryTypes: [selectedType],
}).then(addMarkers);
Once this step is completed, the application will look like the following, with the ability to show markers for each place returned by the Place Search Element:
Now that we have markers on the map, the last step is to handle marker and element click events to show an info window with place details, provided by the Place Details Element. For this example, we will use the Place Details Compact Element.
Add the Place Details Compact Element HTML to your code, for example:
<gmp-place-details-compact orientation="vertical" style="display: none;">
<gmp-place-all-content></gmp-place-all-content>
<gmp-place-attribution light-scheme-color="gray" dark-scheme-color="white"></gmp-place-attribution>
</gmp-place-details-compact>
The style
is set to display: none
; it won't be visible until it's required.
gmp-place-all-content
is passed to render all element content. To choose which
content to render, see the Place Details Compact
Element
documentation.
Create a global variable in JavaScript to hold a reference to the Place Details Compact Element, and populate this in your initialization code, for example:
let placeDetailsElement;
…
placeDetailsElement = document.querySelector('gmp-place-details-compact');
Within the addMarkers
function, add a gmp-click
event listener to each
marker, and configure the Place Details Compact Element to show the place
details by passing the Place ID of the current marker.
Once this is done, an Info Window is opened to display the Place Details Compact Element, anchored on the marker.
Finally, the map is positioned to the viewport of the selected place, making it visible.
async function addMarkers() {
...
marker.addListener('gmp-click', (event) => {
//Set up Place Details Compact Widget
placeDetailsElement.style.display = "block";
// Remove any existing place request element
const existingPlaceRequest = placeDetailsElement.querySelector('gmp-place-details-place-request');
if (existingPlaceRequest) {
existingPlaceRequest.remove();
}
// Create and configure the new place request element
const placeRequestElement = new google.maps.places.PlaceDetailsPlaceRequestElement({ place: place.id });
// Prepend the new place request element to the main widget
placeDetailsElement.prepend(placeRequestElement);
if (infoWindow.isOpen) {
infoWindow.close();
}
infoWindow.setOptions({
content: placeDetailsElement
});
infoWindow.open({
anchor: marker,
map: map
});
// Position the map to show the selected place
placeDetailsElement.addEventListener('gmp-load', () => {
map.fitBounds(place.viewport, { top: 500, left: 400 });
});
});
...
});
}
}
To enable the user to click a place in the Place List Element to show the Place
Details Compact Element, add the following to the JavaScript code after the call
to configureFromSearchNearbyRequest
.
placeListElement.addEventListener("gmp-placeselect", ({ place }) => {
markers[place.id].click();
});
After this step is completed, the application will be able to use either a Nearby Search or Text Search to populate the Place List Element. The results of this will show pins on the map, and clicking a pin or a place in the Place List Element will show an Info Window with place details, provided by the Place Details Compact Element.
The application will look like the following:
Conclusion
The Place Search Element combined with the Place Details Compact Element provides a streamlined way to add rich place discovery features to your Google Maps Platform applications.
Try Places UI Kit today to empower your users to find and explore places using both nearby & text searches, and display rich place details, enhancing their interaction with your place discovery use cases.
Contributors
Henrik Valve | DevX Engineer