Learn how to migrate your existing [Places
API](https://developers.google.com/maps/documentation/places/web-service/overview) or [Place
Class](https://developers.google.com/maps/documentation/javascript/place) implementation to the Places UI Kit
components.

## Who this guide is for

This guide is for developers who have an existing implementation using the
Places API and are interested in updating their code to use Places UI Kit.
It will be most helpful if you are already:

- Making HTTP requests to Places API (New or Legacy) endpoints.
- Using the Place Class within the Maps JavaScript API.
- Handling the API response to render place information in your web application's UI.

## Prerequisites

Enable the [Places UI
Kit](https://developers.google.com/maps/documentation/javascript/places-ui-kit/get-started) on your Google
Cloud Project. You can continue to use your existing API key, or generate a new
one for Places UI Kit. See [Use API
Keys](https://developers.google.com/maps/documentation/javascript/get-api-key) for more information,
including restricting a key.

### Update Maps JavaScript API Loading

The Places UI Kit requires the [Dynamic Library
Import](https://developers.google.com/maps/documentation/javascript/load-maps-js-api#dynamic-library-import)
method of loading the Maps JavaScript API. If you are using the [direct script
loading tag](https://developers.google.com/maps/documentation/javascript/load-maps-js-api#use-legacy-tag),
this must be updated.

Once you have updated the loading script for the Maps JavaScript API, [import
the required
libraries](https://developers.google.com/maps/documentation/javascript/places-ui-kit/get-started#load-the-required-libraries)
to use Places UI Kit.

## Implement the Place Details Element

The [Place Details
Element](https://developers.google.com/maps/documentation/javascript/places-ui-kit/place-details#place-details-element)
and [Place Details Compact
Element](https://developers.google.com/maps/documentation/javascript/places-ui-kit/place-details#place-details-compact-element)
are HTML elements that render details for a place.

### Current Place Details Implementation

- You perform a Place Details call using a HTTP request, or use the JavaScript API Place Class.
- You parse the API response, and display the place details using HTML and CSS.

### Modify HTML Structure for Place Details Element

Identify the HTML container where place details are rendered. Replace your
custom HTML elements (divs, spans for name, address, photos, etc.) with the
Place Details Element html.

There are two elements to pick from:

- Place Details Compact Element
- Place Details Element

For more information about which one to use, see [Place Details
Element](https://developers.google.com/maps/documentation/javascript/places-ui-kit/place-details).

Your existing HTML may look like this.

```html
<div id="my-place-details-container">
    <h2 id="place-name"></h2>
    <p id="place-address"></p>
    <img id="place-photo" src="" alt="Place photo">
    <!-- ... more custom elements -->
</div>
```

Example new HTML, explicitly stating which
[content](https://developers.google.com/maps/documentation/javascript/reference/place-widget-child-elements.md.txt)
to display:

```html
<gmp-place-details-compact orientation="horizontal" truncation-preferred style="display: none;">
    <gmp-place-details-place-request></gmp-place-details-place-request>
    <gmp-place-media lightbox-preferred></gmp-place-media>
    <gmp-place-name></gmp-place-name>
    <gmp-place-address></gmp-place-address>
    <gmp-place-rating></gmp-place-rating>
    <gmp-place-type></gmp-place-type>
    <gmp-place-price></gmp-place-price>
    <gmp-place-accessible-entrance-icon></gmp-place-accessible-entrance-icon>
    <gmp-place-open-now-status></gmp-place-open-now-status>
</gmp-place-details-compact>
```

### Adapt JavaScript Logic for Place Details Element

#### Existing logic

Your existing logic likely involves:

- Retrieving a Place ID.
- Using `PlacesService().getDetails()` or making a web service call.
- Specifying a fields array (for JS API) or FieldMask (for web service) to request specific data.
- In the callback resolution, manually selecting your HTML elements and populating them with the received data.

The following is an example of how you may have Place Details implemented:

```javascript
async function getPlaceDetails(placeId) {
    const { Place } = await google.maps.importLibrary('places');
    // Use place ID to create a new Place instance.
    const place = new Place({
        id: placeId
    });
    await place.fetchFields({
        fields: ['displayName', 'formattedAddress', 'location'],
    });
    // Log the result
    console.log(place.displayName);
    console.log(place.formattedAddress);
}
```

> [!NOTE]
> **Note:** Your logic may look different if you are using a REST API call, or the legacy JavaScript library.

#### New logic

Your new logic will involve:

- Retrieve your Place ID or Place Object.
- Get a reference to the `<gmp-place-details-place-request>` element.
- Pass the Place ID or the Place Object to the place property on the `<gmp-place-details-place-request>` element.

The following is an example of how you can implement the Place Details UI kit in
your JavaScript logic. Get a reference to the Place Details Element. If this
exists, get a reference to the Place Details Place Request element, and set the
place property using a Place ID. In the example HTML code above, the Place
Details Element style is set to `display: none`. This is updated to `display:
block`.

```javascript
function displayPlaceDetailsWithUIKit(placeId) {
  const placeDetailsElement = document.querySelector('gmp-place-details-compact');
  if (placeDetailsElement) {
    const placeDetailsRequest = document.querySelector('gmp-place-details-place-request');
    // Configure the element with the Place ID
    placeDetailsRequest.place = placeId
    placeDetailsElement.style.display = 'block';
    console.log("PlaceDetailsElement configured for place:", placeId);
  } else {
    console.error("PlaceDetailsElement not found in the DOM.");
  }
}

// Example usage:
const placeId = 'ChIJC8HakaIRkFQRiOgkgdHmqkk';
displayPlaceDetailsWithUIKit(placeId);
```

## Implement Place Search Element

The [Place Search
Element](https://developers.google.com/maps/documentation/javascript/places-ui-kit/place-search) is an HTML
element that renders the results of a place search in a list.

### Current Place Search Implementation

- You perform a Text Search or Nearby Search using a HTTP request, or use the JavaScript API Place Class.
- You specify query parameters, location restrictions or biases, types, and requested fields using FieldMask.
- You parse the API response, iterate through the array of places, and manually create HTML list items.

### Modify HTML Structure for Place Search Element

Identify the HTML container where you render your place list. Replace your
custom HTML elements (divs, spans for name, address, etc.) with the Place Search
Element html element.

Your existing HTML may look something like this:

```html
<div id="search-results-area">
    <h3>Nearby Places:</h3>
    <ul id="manual-places-list">
        <!-- JavaScript would dynamically insert list items here -->
        <!-- Example of what JS might generate:
    <li class="place-entry" data-place-id="SOME_PLACE_ID_1">
      <img class="place-icon" src="icon_url_1.png" alt="Icon">
      <span class="place-name">Place Name One</span> -
      <span class="place-vicinity">123 Main St</span>
    </li>
    <li class="place-entry" data-place-id="SOME_PLACE_ID_2">
      <img class="place-icon" src="icon_url_2.png" alt="Icon">
      <span class="place-name">Place Name Two</span> -
      <span class="place-vicinity">456 Oak Ave</span>
    </li>
    -->
        <li class="loading-message">Loading places...</li>
    </ul>
</div>
```

The Place Search Element is implemented using the `<gmp-place-search>`
component. To configure the type of search, include one of the following slotted
configuration components inside:

- `<gmp-place-text-search-request>` for a Text Search.
- `<gmp-place-nearby-search-request>` for a Nearby Search.

To define how results are displayed, you can use the `<gmp-place-all-content>`
shortcut, or provide your own set of individual presentation components. Key
attributes like `selectable` (to allow clicks on list items) and `orientation`
(for a horizontal or vertical layout) can be set directly on the parent
component.

#### Nearby Search example

```html
<gmp-place-search orientation="horizontal" selectable>
    <gmp-place-all-content> </gmp-place-all-content>
    <gmp-place-nearby-search-request></gmp-place-nearby-search-request>
</gmp-place-search>
```

#### Text Search example

```html
<gmp-place-search orientation="horizontal" selectable>
  <gmp-place-all-content> </gmp-place-all-content>
  <gmp-place-text-search-request></gmp-place-text-search-request>
</gmp-place-search>
```

### Adapt JavaScript Logic for Place Search Element

In your JavaScript, get a reference to the search controller component using
`document.querySelector()`. Depending on your setup, this will be either the
`<gmp-place-text-search-request>` or `<gmp-place-nearby-search-request>`
element.

Next, set the properties on this controller to define your search. The required
properties depend on the type of search you are performing.

For a Text Search (`<gmp-place-text-search-request>`), the primary property is
`textQuery`:

```javascript
const textSearchController = document.querySelector('gmp-place-text-search-request');
textSearchController.textQuery = 'museums in London';
```

For a Nearby Search (`<gmp-place-nearby-search-request>`), you must define the
search area using a `locationRestriction`. You can then use `includedTypes` to
filter for specific kinds of places within that area:

```javascript
const nearbySearchController = document.querySelector('gmp-place-nearby-search-request');
nearbySearchController.locationRestriction = new google.maps.Circle({
    center: { lat: 51.5190, lng: -0.1347 },
    radius: 1000
});
nearbySearchController.includedTypes = ['restaurant'];
```

The parent `<gmp-place-search>` component automatically initiates a new search
as soon as its controller's required properties are set.

- For a Text Search, the search runs the moment you assign a value to `textQuery`.
- For a Nearby Search, the search runs after a valid `locationRestriction` is provided.

## Implement Basic Place Autocomplete Element

For developers who require a search experience without the provided UI of Place
Search Element, the [Basic Place
Autocomplete](https://developers.google.com/maps/documentation/javascript/places-ui-kit/basic-autocomplete)
Element is available.

This element is ideal for creating a search input field while maintaining
complete control over how the results are displayed in your custom user
interface. The Autocomplete Element's sole responsibility is to provide place
predictions as the user types and programmatically expose a Place ID for the
selected place.

It does not display any details itself, or provide any other programmatically
accessible information.

### Current Place Autocomplete Implementation

Your existing logic likely involves:

- Rendering a text input field on your page which calls Place Autocomplete as the user types, displaying results.
- Using the Place ID of the user selected place to fetch more details, for example using the Place Details API.
- Displaying details of the selected place.

### Modify HTML Structure for Basic Place Autocomplete Element

Identify and remove the HTML element you attach the Autocomplete widget to. It's
likely using a standard HTML input field.

```html
<input id="pac-input" type="text" placeholder="Search for a location" />
```

Example new HTML, using the web component approach to initialize a Basic Place
Autocomplete element on your page.

```html
<gmp-basic-place-autocomplete></gmp-basic-place-autocomplete>
```

### Adapt JavaScript Logic for Basic Place Autocomplete Element

Your JavaScript logic likely involves creating the Autocomplete widget attached
to an `input` HTML element. This widget then listens for the `place_changed`
event, triggering an action with the returned data.

Example existing JavaScript to remove:

```javascript
// Get the input element
const input = document.getElementById("pac-input");

// Create the Autocomplete widget instance
const autocomplete = new google.maps.places.Autocomplete(input, {
  fields: ["place_id", "geometry", "name"]
});

// Add a listener for the 'place_changed' event
autocomplete.addListener("place_changed", () => {
  // Your logic to get and display place information
  console.log(place.place_id);
});
```

Your new JavaScript logic will get a reference to the Basic Place Autocomplete
Element, and listen for `gmp-select` events:

```javascript
const placeAutocomplete = document.querySelector('gmp-basic-place-autocomplete');

placeAutocomplete.addEventListener('gmp-select', (event) => {
  console.log(event.place);
});
```

On select of a place in the Autocomplete drop-down, the `gmp-select` event will
fire. The Place ID of the selected place can be retrieved from the `event`
object. The Place ID can then be used to initialize an instance of the [Place
Details Element](https://developers.google.com/maps/documentation/javascript/places-ui-kit/place-details), to
display the selected place details.

## Handle Customization

> [!TIP]
> **Tip:** For detailed guidance on customizing the look and feel, including a live styling tool and attribution requirements, refer to the [Places UI Kit Custom
> Styling](https://developers.google.com/maps/documentation/javascript/places-ui-kit/custom-styling) documentation.

### Place Details Element customization

#### Orientation

The Place Details Element can be rendered in both Horizontal and Vertical
orientation. Use the `orientation` attribute on `gmp-place-details-compact` to
choose between vertical and horizontal. For example:

`<gmp-place-details-compact orientation="vertical">`

#### Choose fields to render

Use content elements to specify the content to be rendered within the Place
Details Element. Add the content elements directly to the Place Details Element.
For example, excluding the content element `<gmp-place-type>` would stop the
Place Details Element rendering the Place Type of the selected place. Only the
content elements that you include are rendered, so include `<gmp-place-name>` to
show the place name. For a full list of content elements, see the [Place Widget
Content
Customization](https://developers.google.com/maps/documentation/javascript/reference/place-widget-child-elements)
reference documentation.

Adding or removing fields from the Place Details Element does not change the
cost of rendering the element on the page.

#### Set CSS Styles

Custom CSS properties are available to configure the element's colors and fonts.
For example, to set the element background to green, set the following CSS
property:

```css
gmp-place-details-compact {
  --gmp-mat-color-surface: green;
}
```

See the reference documentation for
[`PlaceDetailsCompactElement`](https://developers.google.com/maps/documentation/javascript/reference/places-widget.md.txt#PlaceDetailsCompactElement-CSS-Properties)
for more details.

### Place Search Element customization

#### Orientation

The Place Search Element can be rendered in both Horizontal and Vertical
orientation. Use the `orientation` attribute on `<gmp-place-search>` to choose
between vertical and horizontal. For example:

```html
<gmp-place-search orientation="horizontal" selectable>
```

#### Choose fields to render

Use content elements to specify the content to be rendered within the Place
Search Element. The element `<gmp-place-all-content>` can be used to display all
content, or a selection of html tags can be used to configure the rendered
content.

To configure the rendered content, add the content elements to a `<template
slot="details-item">` element inside `<gmp-place-search>`. For example,
including only `<gmp-place-name>` and `<gmp-place-address>` in the template
would render only the name and address for each place:

```html
<gmp-place-search orientation="horizontal" selectable>
  <template slot="details-item">
    <gmp-place-name></gmp-place-name>
    <gmp-place-address></gmp-place-address>
  </template>
  <gmp-place-text-search-request></gmp-place-text-search-request>
</gmp-place-search>
```

### Basic Place Autocomplete Element customization

#### Set CSS Styles

Custom CSS properties are available to customize the Autocomplete element's look
and feel. For example, to set the background color to light purple, you would
set the `background-color` property on the element.

```css
gmp-basic-place-autocomplete {
  background-color: #d993e6;
}
```

See the
[BasicPlaceAutocompleteElement](https://developers.google.com/maps/documentation/javascript/reference/next/places-widget#BasicPlaceAutocompleteElement-CSS-Properties)
reference documentation for more details.

## Handle events \& data

The Places UI Kit Elements are interactive components that allow you to listen
for events and retrieve data programmatically.

### Listen for Events

You can add event listeners to the elements to trigger actions based on user
interaction or the element's state.

#### Selection Event

- `gmp-select`: This event is fired when a user makes a selection.
  - On the Place Search Element, it's triggered when a user clicks a place in the results list.
  - On the Basic Place Autocomplete Element, it's triggered when a user clicks a prediction in the drop-down list.

#### Common Events

The Place Search, Place Details, and Basic Place Autocomplete elements all
support the following events:

- `gmp-load`: Fired when the element and its content have finished loading and rendering.
- `gmp-requesterror`: Fired when a request to the server fails, for example, due to an invalid API key.

### Access Element Data Programmatically

You can programmatically retrieve specific data from the elements after they
have been interacted with or loaded.

- For the Place Search Element and the Place Details Element, you can retrieve the following information:
  - Place ID
  - Location (Latitude \& Longitude)
  - Viewport
- For the Basic Place Autocomplete Element, you can retrieve the following information:
  - Place ID

All other data contained within the elements is not programmatically accessible.

For more detailed examples, see the individual documentation for the [Place
Search Element](https://developers.google.com/maps/documentation/javascript/places-ui-kit/place-search),
[Place Details Element](https://developers.google.com/maps/documentation/javascript/places-ui-kit/place-details.md.txt)
, and the [Basic Place Autocomplete
Element](https://developers.google.com/maps/documentation/javascript/places-ui-kit/basic-autocomplete).

## Testing and Refinement

Once you have integrated Places UI Kit element(s), testing is crucial for a
smooth transition and a positive user experience. Your testing should cover
several key areas, addressing all elements you have implemented: the Place
Details, Place Search, and Basic Place Autocomplete elements.

### Place Details Element

For the Place Details Element, begin by verifying that details are displayed
correctly for a diverse range of places. Test by passing various Place IDs to
the `.place` property of the `<gmp-place-details-place-request>` element. Use
IDs representing different establishment types (businesses with rich data,
points of interest, basic addresses) and places in different regions or
languages. Pay close attention to the formatting, layout, and presence of the
content.

### Place Search Element

If you've implemented the Place Search Element, verify its rendering and
behavior under different search scenarios.

- For a Text Search, test by setting the `textQuery` property on the `<gmp-place-text-search-request>` element with various inputs: broad queries, specific addresses, and queries with location biases.
- For a Nearby Search, test by setting the `locationRestriction` and `includedTypes` properties on the `<gmp-place-nearby-search-request>` element. Use different location sizes, and type filters.

Confirm that the list populates with relevant results and that the `gmp-select`
event fires correctly upon selection.

### Basic Place Autocomplete Element

For the Basic Place Autocomplete Element, focus testing on user interaction and
the data passed by the selection event. Confirm that the `gmp-select` event
fires reliably when a user clicks a prediction. Verify that the `event.place`
object in the event handler contains a valid Place ID.

Most importantly, test the end-to-end flow: select a place from the Autocomplete
drop-down and verify its Place ID can be successfully used to populate another
element, such as the Place Details Element.

### Error handling

Rigorous testing of error handling is essential across all components. Simulate
passing invalid or non-existent Place IDs to the Place Details Element, or using
invalid search parameters for the Place Search Element. Trigger the
`gmp-requesterror` event by simulating network issues or using an invalid API
key to make sure your application handles it gracefully. Implement user-friendly
error messages and logging to prevent a broken or confusing UI.