Privacy: Always request user permission before accessing geolocation. Provide
a fallback for users who deny permission.
Multi-Step Forms
Manage autocomplete instances across multiple form steps with proper cleanup.
let currentAutocomplete =null;let formData ={billingAddress:null,shippingAddress:null};functioninitialiseStep(step){// Clean up previous instanceif(currentAutocomplete){
currentAutocomplete.destroy();}const containerId = step ===1?'billing-address':'shipping-address';
currentAutocomplete =newPlacesAutocomplete({containerId: containerId,googleMapsApiKey:'YOUR_API_KEY',onResponse:(placeDetails)=>{if(step ===1){
formData.billingAddress = placeDetails;}else{
formData.shippingAddress = placeDetails;}// Enable next button
document.getElementById('next-btn').disabled =false;},options:{autofocus:true}});}// Initialize first stepinitialiseStep(1);// Handle step navigation
document.getElementById('next-btn').addEventListener('click',()=>{const currentStep =getCurrentStep();if(currentStep ===1){showStep(2);initialiseStep(2);}else{submitForm(formData);}});
Important: Always call destroy() before creating a
new instance to prevent memory leaks and event listener duplication.
Error Handling
Implement robust error handling with user-friendly messages for different error scenarios.
const autocomplete =newPlacesAutocomplete({containerId:'autocomplete-container',googleMapsApiKey:'YOUR_API_KEY',onResponse:(placeDetails)=>{// Clear any previous errorshideError();// Validate the responseif(!placeDetails.addressComponents){showError('Unable to retrieve full address details. Please try again.');return;}// Process the place detailsprocessAddress(placeDetails);},onError:(error)=>{
console.error('Autocomplete error:', error);// Handle specific error typesif(error.message?.includes('ZERO_RESULTS')){showError('No results found. Please try a different search term.');}elseif(error.message?.includes('OVER_QUERY_LIMIT')){showError('Service temporarily unavailable. Please try again later.');}elseif(error.message?.includes('REQUEST_DENIED')){showError('Service configuration error. Please contact support.');}else{showError('An error occurred. Please try again.');}}});functionshowError(message){const errorDiv = document.getElementById('error-message');
errorDiv.textContent = message;
errorDiv.classList.remove('hidden');}functionhideError(){
document.getElementById('error-message').classList.add('hidden');}
Distance-Based Search
Display distances from a fixed origin point and optionally restrict search radius.
const autocomplete =newPlacesAutocomplete({containerId:'autocomplete-container',googleMapsApiKey:'YOUR_API_KEY',requestParams:{origin:{lat:51.5074,lng:-0.1278},// London// Optional: restrict to a specific radiuslocationRestriction:{lat:51.5074,lng:-0.1278,radius:100000// 100km}},options:{distance:true,distance_units:'km'},onResponse:(placeDetails)=>{
console.log('Selected place:', placeDetails);// Distance is shown in the suggestions automatically// You can also calculate your own distance if neededif(placeDetails.location){const distance =calculateDistance({lat:51.5074,lng:-0.1278},
placeDetails.location
);
console.log('Distance from London:', distance,'km');}}});// Haversine formula for distance calculationfunctioncalculateDistance(point1, point2){constR=6371;// Earth's radius in kmconst dLat =toRad(point2.lat - point1.lat);const dLon =toRad(point2.lng - point1.lng);const lat1 =toRad(point1.lat);const lat2 =toRad(point2.lat);const a = Math.sin(dLat/2)* Math.sin(dLat/2)+
Math.sin(dLon/2)* Math.sin(dLon/2)*
Math.cos(lat1)* Math.cos(lat2);const c =2* Math.atan2(Math.sqrt(a), Math.sqrt(1-a));returnR* c;}functiontoRad(degrees){return degrees * Math.PI/180;}
Note: Distance is automatically displayed in suggestions when origin is provided in
requestParams and options.distance is true.
Retain Input Value After Selection
Keep the selected address visible in the input field instead of clearing it.
const autocomplete =newPlacesAutocomplete({containerId:'autocomplete-container',googleMapsApiKey:'YOUR_API_KEY',options:{clear_input:false,// Keep the address in the input fieldplaceholder:'Enter your address...'},onResponse:(placeDetails)=>{// The input field will now show the formattedAddress
console.log('Selected:', placeDetails.formattedAddress);// You can still access the full details
console.log('Full details:', placeDetails);}});
Single Page Application (SPA) Integration
Properly manage component lifecycle in SPAs to prevent memory leaks.
// app.js or routing fileclassAddressComponent{constructor(containerId, apiKey){this.containerId = containerId;this.apiKey = apiKey;this.autocomplete =null;}mount(){this.autocomplete =newPlacesAutocomplete({containerId:this.containerId,googleMapsApiKey:this.apiKey,onResponse:(placeDetails)=>{this.handlePlaceSelection(placeDetails);}});}unmount(){if(this.autocomplete){this.autocomplete.destroy();this.autocomplete =null;}}handlePlaceSelection(placeDetails){// Emit event or update statethis.onPlaceSelected?.(placeDetails);}}// Usage with routingconst router ={'/checkout':{onEnter:()=>{const addressComponent =newAddressComponent('address-input','YOUR_API_KEY');
addressComponent.mount();// Store reference for cleanup
window.currentComponents ={ addressComponent };},onLeave:()=>{
window.currentComponents?.addressComponent?.unmount();}}};
Critical: Always clean up instances when navigating away from views to prevent
memory leaks and duplicate event listeners.
More Examples
Check out additional working examples in the main examples section: