PlaceAutocompleteElement
in Angular 19
In this blog, we’ll explore how to integrate the Google Places API in an Angular 19 application using the new PlaceAutocompleteElement
. This modern approach offers a native element for place predictions, reducing the need for verbose directive wrappers or third-party libraries.
By the end, you’ll learn:
PlaceAutocompleteElement
is a game-changer
The Google Places API lets developers access comprehensive information about millions of places globally. It supports:
Ideal for:
1. Firebase Console (optional for broader use):
environment.ts
2. Google Cloud Console:
// environment.ts
export const environment = {
production: false,
googleMapsApiKey: 'YOUR_API_KEY_HERE'
};
To load the Google Maps JavaScript API only once and avoid race conditions, we’ll create a dedicated service.
googlemap.service.ts
:
import { Injectable } from '@angular/core';
import { environment } from '../environments/environment';
@Injectable({ providedIn: 'root' })
export class GoogleMapService {
private static googleMapPromise: Promise<typeof google.maps> | null = null;
private static readonly CALLBACK_NAME = 'GooglePlaces_cb';
private static readonly API_KEY = environment.googleMapsApiKey;
public getGoogleMapPlaces() {
return this.loadGoogleMapPlace();
}
private loadGoogleMapPlace(): Promise<typeof google.maps> {
if (GoogleMapService.googleMapPromise) return GoogleMapService.googleMapPromise;
const existingScript = document.getElementById('google-places-js-script');
if (existingScript) return this.getLoadedGoogleMap();
return this.setGoogleMapScript();
}
private getLoadedGoogleMap(): Promise<typeof google.maps> {
return new Promise((resolve, reject) => {
if ((window as any).google?.maps) return resolve((window as any).google.maps);
(window as any)[GoogleMapService.CALLBACK_NAME] = () => resolve((window as any).google.maps);
const script = document.getElementById('google-places-js-script');
if (script) script.onerror = reject;
});
}
private setGoogleMapScript(): Promise<typeof google.maps> {
GoogleMapService.googleMapPromise = new Promise((resolve, reject) => {
(window as any)[GoogleMapService.CALLBACK_NAME] = () => resolve((window as any).google.maps);
const script = document.createElement('script');
script.id = 'google-places-js-script';
script.src = this.getScriptSrc(GoogleMapService.CALLBACK_NAME);
script.async = true;
script.defer = true;
script.onerror = reject;
document.body.appendChild(script);
});
return GoogleMapService.googleMapPromise;
}
private getScriptSrc(callback: string): string {
const query = new URLSearchParams({
v: 'weekly',
callback,
key: GoogleMapService.API_KEY,
libraries: 'places',
language: 'en'
}).toString();
return `https://maps.googleapis.com/maps/api/js?${query}`;
}
}
Why These Methods?
getGoogleMapPlaces()
: Public method for components to trigger the script load.loadGoogleMapPlace()
: Checks if script is already loaded or in progress.getLoadedGoogleMap()
: Waits for an existing script to finish loading.setGoogleMapScript()
: Dynamically adds the Google Maps JS SDK.getScriptSrc()
: Constructs the script URL with required parameters.
Using Angular’s standalone component support (available in v15+), we’ll make a modular and reusable place autocomplete component.
placesautocompleteelement.component.ts
:
import { CommonModule } from '@angular/common';
import {
Component,
ElementRef,
inject,
signal,
viewChild,
} from '@angular/core';
import { GoogleMapService } from '../googlemap.service';
@Component({
selector: 'auto-complete-ele',
standalone: true,
imports: [CommonModule],
templateUrl: './auto-complete-ele.html',
})
export class AutoCompleteElement {
private readonly googleMapService = inject(GoogleMapService);
public readonly addressGroupContainer = viewChild<ElementRef<HTMLDivElement>>('addressGroupContainer');
public readonly placeJson = signal(null);
async ngOnInit() {
const maps = await this.googleMapService.getGoogleMapPlaces();
const placeAutocomplete = new maps.places.PlaceAutocompleteElement({
types: ['geocode'],
});
this.addressGroupContainer()?.nativeElement.appendChild(placeAutocomplete);
placeAutocomplete.addEventListener('gmp-select', async ({ placePrediction }: any) => {
const place = placePrediction.toPlace();
await place.fetchFields({
fields: ['displayName', 'formattedAddress', 'location', 'addressComponents'],
});
this.placeJson.set(place.toJSON());
});
}
}
placesautocompleteelement.component.html
:
<div>
<label for="">Search Google Places</label>
<div class="address-group position-relative" #addressGroupContainer></div>
@if (placeJson()) {
<div>
<pre>{{ placeJson() | json }}</pre>
</div>
}
</div>
Google’s PlaceAutocompleteElement
is a Web Component introduced to simplify place predictions without needing to manually handle text input, debouncing, or prediction list management.
Benefits:
gmp-select
)
index.html
; instead, load it only when needed.
The new PlaceAutocompleteElement
paired with Angular 19’s modern features (like standalone components and signals) makes it incredibly straightforward to build responsive, reactive, and user-friendly autocomplete UIs.
By breaking the integration into services and components, you maintain modularity and separation of concerns.
Check out the working demos to see the Google Places Autocomplete in action:
StackBlitz Live Demo:
Open in StackBlitz
Source Code on GitHub:
View on GitHub
Explore, fork, and experiment with the code to accelerate your integration!
You could extend this example with:
Happy coding! 🧑💻🌐