Skip to content

Commit d990243

Browse files
crisbetojelbourn
authored andcommitted
fix(google-maps): handle trying to access the map before it has been initialized (#17805)
As things are set up at the moment, the Google `Map` object will be initialized once the API has loaded, however all of the methods on the `GoogleMap` component assume that the object will always be defined. This means that if any of the methods are called before it is initialized, we'll throw a null pointer error. These changes add a more readable error so people know what to do.
1 parent 61b423a commit d990243

File tree

1 file changed

+32
-10
lines changed

1 file changed

+32
-10
lines changed

src/google-maps/google-map/google-map.ts

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ export class GoogleMap implements OnChanges, OnInit, OnDestroy {
190190
@Output() zoomChanged = new EventEmitter<void>();
191191

192192
private _mapEl: HTMLElement;
193-
_googleMap!: UpdatedGoogleMap;
193+
_googleMap: UpdatedGoogleMap;
194194

195195
/** Whether we're currently rendering inside a browser. */
196196
private _isBrowser: boolean;
@@ -244,8 +244,7 @@ export class GoogleMap implements OnChanges, OnInit, OnDestroy {
244244
this._googleMapChanges = this._initializeMap(combinedOptionsChanges);
245245
this._googleMapChanges.subscribe((googleMap: google.maps.Map) => {
246246
this._googleMap = googleMap as UpdatedGoogleMap;
247-
248-
this._initializeEventHandlers();
247+
this._initializeEventHandlers(this._googleMap);
249248
});
250249

251250
this._watchForOptionsChanges();
@@ -267,6 +266,7 @@ export class GoogleMap implements OnChanges, OnInit, OnDestroy {
267266
fitBounds(
268267
bounds: google.maps.LatLngBounds|google.maps.LatLngBoundsLiteral,
269268
padding?: number|google.maps.Padding) {
269+
this._assertInitialized();
270270
this._googleMap.fitBounds(bounds, padding);
271271
}
272272

@@ -275,6 +275,7 @@ export class GoogleMap implements OnChanges, OnInit, OnDestroy {
275275
* https://developers.google.com/maps/documentation/javascript/reference/map#Map.panBy
276276
*/
277277
panBy(x: number, y: number) {
278+
this._assertInitialized();
278279
this._googleMap.panBy(x, y);
279280
}
280281

@@ -283,6 +284,7 @@ export class GoogleMap implements OnChanges, OnInit, OnDestroy {
283284
* https://developers.google.com/maps/documentation/javascript/reference/map#Map.panTo
284285
*/
285286
panTo(latLng: google.maps.LatLng|google.maps.LatLngLiteral) {
287+
this._assertInitialized();
286288
this._googleMap.panTo(latLng);
287289
}
288290

@@ -293,6 +295,7 @@ export class GoogleMap implements OnChanges, OnInit, OnDestroy {
293295
panToBounds(
294296
latLngBounds: google.maps.LatLngBounds|google.maps.LatLngBoundsLiteral,
295297
padding?: number|google.maps.Padding) {
298+
this._assertInitialized();
296299
this._googleMap.panToBounds(latLngBounds, padding);
297300
}
298301

@@ -301,6 +304,7 @@ export class GoogleMap implements OnChanges, OnInit, OnDestroy {
301304
* https://developers.google.com/maps/documentation/javascript/reference/map#Map.getBounds
302305
*/
303306
getBounds(): google.maps.LatLngBounds|null {
307+
this._assertInitialized();
304308
return this._googleMap.getBounds() || null;
305309
}
306310

@@ -309,6 +313,7 @@ export class GoogleMap implements OnChanges, OnInit, OnDestroy {
309313
* https://developers.google.com/maps/documentation/javascript/reference/map#Map.getCenter
310314
*/
311315
getCenter(): google.maps.LatLng {
316+
this._assertInitialized();
312317
return this._googleMap.getCenter();
313318
}
314319

@@ -317,6 +322,7 @@ export class GoogleMap implements OnChanges, OnInit, OnDestroy {
317322
* https://developers.google.com/maps/documentation/javascript/reference/map#Map.getClickableIcons
318323
*/
319324
getClickableIcons(): boolean {
325+
this._assertInitialized();
320326
return this._googleMap.getClickableIcons();
321327
}
322328

@@ -325,6 +331,7 @@ export class GoogleMap implements OnChanges, OnInit, OnDestroy {
325331
* https://developers.google.com/maps/documentation/javascript/reference/map#Map.getHeading
326332
*/
327333
getHeading(): number {
334+
this._assertInitialized();
328335
return this._googleMap.getHeading();
329336
}
330337

@@ -333,6 +340,7 @@ export class GoogleMap implements OnChanges, OnInit, OnDestroy {
333340
* https://developers.google.com/maps/documentation/javascript/reference/map#Map.getMapTypeId
334341
*/
335342
getMapTypeId(): google.maps.MapTypeId|string {
343+
this._assertInitialized();
336344
return this._googleMap.getMapTypeId();
337345
}
338346

@@ -341,6 +349,7 @@ export class GoogleMap implements OnChanges, OnInit, OnDestroy {
341349
* https://developers.google.com/maps/documentation/javascript/reference/map#Map.getProjection
342350
*/
343351
getProjection(): google.maps.Projection|null {
352+
this._assertInitialized();
344353
return this._googleMap.getProjection();
345354
}
346355

@@ -349,6 +358,7 @@ export class GoogleMap implements OnChanges, OnInit, OnDestroy {
349358
* https://developers.google.com/maps/documentation/javascript/reference/map#Map.getStreetView
350359
*/
351360
getStreetView(): google.maps.StreetViewPanorama {
361+
this._assertInitialized();
352362
return this._googleMap.getStreetView();
353363
}
354364

@@ -357,6 +367,7 @@ export class GoogleMap implements OnChanges, OnInit, OnDestroy {
357367
* https://developers.google.com/maps/documentation/javascript/reference/map#Map.getTilt
358368
*/
359369
getTilt(): number {
370+
this._assertInitialized();
360371
return this._googleMap.getTilt();
361372
}
362373

@@ -365,6 +376,7 @@ export class GoogleMap implements OnChanges, OnInit, OnDestroy {
365376
* https://developers.google.com/maps/documentation/javascript/reference/map#Map.getZoom
366377
*/
367378
getZoom(): number {
379+
this._assertInitialized();
368380
return this._googleMap.getZoom();
369381
}
370382

@@ -373,6 +385,7 @@ export class GoogleMap implements OnChanges, OnInit, OnDestroy {
373385
* https://developers.google.com/maps/documentation/javascript/reference/map#Map.controls
374386
*/
375387
get controls(): Array<google.maps.MVCArray<Node>> {
388+
this._assertInitialized();
376389
return this._googleMap.controls;
377390
}
378391

@@ -381,6 +394,7 @@ export class GoogleMap implements OnChanges, OnInit, OnDestroy {
381394
* https://developers.google.com/maps/documentation/javascript/reference/map#Map.data
382395
*/
383396
get data(): google.maps.Data {
397+
this._assertInitialized();
384398
return this._googleMap.data;
385399
}
386400

@@ -389,6 +403,7 @@ export class GoogleMap implements OnChanges, OnInit, OnDestroy {
389403
* https://developers.google.com/maps/documentation/javascript/reference/map#Map.mapTypes
390404
*/
391405
get mapTypes(): google.maps.MapTypeRegistry {
406+
this._assertInitialized();
392407
return this._googleMap.mapTypes;
393408
}
394409

@@ -397,6 +412,7 @@ export class GoogleMap implements OnChanges, OnInit, OnDestroy {
397412
* https://developers.google.com/maps/documentation/javascript/reference/map#Map.overlayMapTypes
398413
*/
399414
get overlayMapTypes(): google.maps.MVCArray<google.maps.MapType> {
415+
this._assertInitialized();
400416
return this._googleMap.overlayMapTypes;
401417
}
402418

@@ -423,9 +439,8 @@ export class GoogleMap implements OnChanges, OnInit, OnDestroy {
423439
private _initializeMap(optionsChanges: Observable<google.maps.MapOptions>):
424440
Observable<google.maps.Map> {
425441
return optionsChanges.pipe(
426-
take(1), map(options => {
427-
return new google.maps.Map(this._mapEl, options);
428-
}),
442+
take(1),
443+
map(options => new google.maps.Map(this._mapEl, options)),
429444
shareReplay(1));
430445
}
431446

@@ -457,7 +472,7 @@ export class GoogleMap implements OnChanges, OnInit, OnDestroy {
457472
});
458473
}
459474

460-
private _initializeEventHandlers() {
475+
private _initializeEventHandlers(googleMap: UpdatedGoogleMap) {
461476
// Ensure that we don't leak if called multiple times.
462477
this._clearListeners();
463478

@@ -484,7 +499,7 @@ export class GoogleMap implements OnChanges, OnInit, OnDestroy {
484499
]);
485500
eventHandlers.forEach((eventHandler: EventEmitter<void>, name: string) => {
486501
if (eventHandler.observers.length > 0) {
487-
this._listeners.push(this._googleMap.addListener(name, () => {
502+
this._listeners.push(googleMap.addListener(name, () => {
488503
eventHandler.emit();
489504
}));
490505
}
@@ -493,13 +508,13 @@ export class GoogleMap implements OnChanges, OnInit, OnDestroy {
493508
(eventHandler: EventEmitter<google.maps.MouseEvent>, name: string) => {
494509
if (eventHandler.observers.length > 0) {
495510
this._listeners.push(
496-
this._googleMap.addListener(name, (event: google.maps.MouseEvent) => {
511+
googleMap.addListener(name, (event: google.maps.MouseEvent) => {
497512
eventHandler.emit(event);
498513
}));
499514
}
500515
});
501516
if (this.mapClick.observers.length > 0) {
502-
this._listeners.push(this._googleMap.addListener(
517+
this._listeners.push(googleMap.addListener(
503518
'click', (event: google.maps.MouseEvent|google.maps.IconMouseEvent) => {
504519
this.mapClick.emit(event);
505520
}));
@@ -514,4 +529,11 @@ export class GoogleMap implements OnChanges, OnInit, OnDestroy {
514529

515530
this._listeners = [];
516531
}
532+
533+
private _assertInitialized() {
534+
if (!this._googleMap) {
535+
throw Error('Cannot access Google Map information before the API has been initialized. ' +
536+
'Please wait for the API to load before trying to interact with it.');
537+
}
538+
}
517539
}

0 commit comments

Comments
 (0)