I managed to lazy load Angular's built-in Google Maps component as stated in the official doc:
export class GoogleMapsDemoComponent {
apiLoaded: Observable<boolean>;
geoCoder: any;
constructor(httpClient: HttpClient) {
this.apiLoaded = httpClient.jsonp('https://maps.googleapis.com/maps/api/js?key=YOUR_KEY_HERE', 'callback')
.pipe(
map(() => true),
catchError(() => of(false)),
);
}
ngOnInit(): void {
this.apiLoaded.subscribe(() => this.initGeoCoder());
}
initGeoCoder() {
this.geoCoder = new google.maps.Geocoder();
}
}
I'm running into errors now though if the component gets initialised multiple times.
You have included the Google Maps JavaScript API multiple times on this page. This may cause unexpected errors.
So I want to move the loading of the Google Script to a dedicated service and inject it into all components that need it.
There is a discussion in the GitHub repo confirming this approach:
You should be able to refactor the httpClient.jsonp('https://maps.googleapis.com/maps/api/js?key=YOUR_KEY_HERE', 'callback') and surrounding api loading into a service so that it can act as a singleton and prevent multiple loads. Note you will want to add providedIn: 'root' to your @Injectable so that it does not create an instance per module and thus load the api for each instance.
I don't managed to do that properly though, I constantly get the following error message that appears to be raised when the Google script is not loaded yet:
ERROR ReferenceError: google is not defined
Service:
export class GeoService {
apiLoaded: Observable<boolean>;
constructor(private http: HttpClient) {
this.apiLoaded = this.http
.jsonp(
'https://maps.googleapis.com/maps/api/js?key=API_KEY',
'callback'
)
.pipe(
map(() => true),
catchError((error) => of(error))
);
}
}
Component:
export class GoogleMapsDemoComponent {
apiLoaded: Observable<boolean>;
geoCoder: any;
constructor(geo: GeoService) {}
ngOnInit(): void {
this.geo.apiLoaded.subscribe(() => this.initGeoCoder());
}
initGeoCoder() {
this.geoCoder = new google.maps.Geocoder();
}
}
My service is in a shared module that is being imported into the module of the component. I also tried to use a service inside the same module just to make sure I'm not messing up import, but I received the same error message.
Can anyone tell me what I'm missing here?