Checkout Form Integration

One of the most powerful use cases for the Places Autocomplete component is to simplify address entry in forms. This example demonstrates how to capture the detailed address data from a user's selection and use it to automatically populate the fields of a checkout form.

Live Demo

Begin typing an address in the search box. After selecting a suggestion, the form fields below will be automatically filled with the corresponding address components.

powered by
powered by Google

How It Works

The key to this functionality is fetching and parsing the `addressComponents` array provided by the Google Places API.

  1. Request `addressComponents`: We must explicitly ask for the `addressComponents` field by including it in the `fetchFields` prop. This is essential for getting the detailed, structured address data.
  2. Handle the Response: In the `onResponse` event handler, we receive the `PlaceResult` object which now contains the `addressComponents` array.
  3. Parse the Components: Each object in the `addressComponents` array has a `types` array that identifies what kind of data it holds (e.g., `'street_number'`, `'locality'` for city, `'postal_code'`). We can iterate through or `find` the components we need.
  4. Populate the Form: Once we've found a component, we use its `longText` or `shortText` value to populate the corresponding field in our reactive `$state` form object, which is bound to the input fields.

Full Code Example

Here is the complete code for the checkout form example. You can adapt this logic to fit the specific fields your own forms require.

<script lang="ts">
import { PlaceAutocomplete } from 'places-autocomplete-svelte';
import type { PlaceResult, ComponentOptions } from 'places-autocomplete-svelte/interfaces';

let { data } = $props();
const PUBLIC_GOOGLE_MAPS_API_KEY = data?.PUBLIC_GOOGLE_MAPS_API_KEY;

// --- Form State ---
// Use $state to create a reactive object for our form fields
let form = $state({
	street_number: '',
	route: '', // Street name
	locality: '', // City
	administrative_area_level_1: '', // State/Province
	country: '',
	postal_code: ''
});

// --- Component State ---
let placesError = $state('');
let fullResponse: PlaceResult | null = $state(null);

// --- Component Configuration ---
const fetchFields = ['addressComponents', 'formattedAddress'];

// Set clear_input: false to keep the address visible after selection.
const options: ComponentOptions = {
	placeholder: 'Start typing your address...',
	clear_input: false
};

// --- Event Handlers ---
const onError = (error: string) => (placesError = error);

const onResponse = (response: PlaceResult) => {
	fullResponse = response;
	// Reset form fields before populating
	for (const key in form) {
		form[key as keyof typeof form] = '';
	}

	// Helper function to find a specific address component
	const getAddressComponent = (type: string) =>
		response.addressComponents?.find((c) => c.types.includes(type))?.longText || '';

	// Populate the form state with values from the response
	form.street_number = getAddressComponent('street_number');
	form.route = getAddressComponent('route');
	form.locality = getAddressComponent('postal_town') || getAddressComponent('locality');
	form.administrative_area_level_1 = getAddressComponent('administrative_area_level_1');
	form.country = getAddressComponent('country');
	form.postal_code = getAddressComponent('postal_code');
};
</script>


{#if placesError}
	<div class="mt-4 rounded-md bg-red-100 p-4 text-red-800">
		<p class="font-semibold text-red-800">Error</p>
		<p>{placesError}</p>
	</div>
{/if}
<PlaceAutocomplete
    {PUBLIC_GOOGLE_MAPS_API_KEY}
    {options}
    {onError}
	{onResponse}
/>
<div class="grid grid-cols-1 gap-4 md:grid-cols-2">
	<div class="mx-auto w-full max-w-md">
		<label for="address1" class="block text-sm font-medium text-slate-200">Address:</label>
		<input
			type="text"
			id="address1"
			class="mt-2 block w-full rounded-md border border-gray-300 bg-slate-700 p-2 text-slate-300"
			bind:value={obj.street_number}
		/>
	</div>
	<div class="mx-auto w-full max-w-md">
		<label for="city" class="block text-sm font-medium text-slate-200">City:</label>
		<input
			id="city"
			class="mt-2 block w-full rounded-md border border-gray-300 bg-slate-700 p-2 text-slate-300"
			bind:value={obj.locality}
		/>
	</div>
	<div class="mx-auto w-full max-w-md">
		<label for="postcode" class="block text-sm font-medium text-slate-200">Postal Code:</label>
		<input
			type="text"
			id="postcode"
			class="mt-2 block w-full rounded-md border border-gray-300 bg-slate-700 p-2 text-slate-300"
			bind:value={obj.postal_code}
		/>
	</div>
	<div class="mx-auto w-full max-w-md">
		<label for="country" class="block text-sm font-medium text-slate-200">Country:</label>
		<input
			type="text"
			id="country"
			class="mt-2 block w-full rounded-md border border-gray-300 bg-slate-700 p-2 text-slate-300"
			bind:value={obj.country}
		/>
	</div>
</div>

2025 Places Autocomplete Svelte.