From 90f4d0e6a4536875ec54aeec5d413b00b6738c47 Mon Sep 17 00:00:00 2001 From: Kristiyan Kostadinov Date: Mon, 27 Jul 2020 21:18:25 +0200 Subject: [PATCH] fix(google-maps): avoid re-initializing info window for same marker (#19299) Currently if `open` is called multiple times for the same object, we keep re-initializing the info window. This can be seen in the dev app, because Chrome keeps logging warnings for some event listeners. These changes add a check that keeps the existing info window. --- .../map-info-window/map-info-window.spec.ts | 25 +++++++++++++++++++ .../map-info-window/map-info-window.ts | 9 +++++-- .../testing/fake-google-map-utils.ts | 6 ++++- 3 files changed, 37 insertions(+), 3 deletions(-) diff --git a/src/google-maps/map-info-window/map-info-window.spec.ts b/src/google-maps/map-info-window/map-info-window.spec.ts index 3de13ded3630..5c34d03fd51f 100644 --- a/src/google-maps/map-info-window/map-info-window.spec.ts +++ b/src/google-maps/map-info-window/map-info-window.spec.ts @@ -129,6 +129,31 @@ describe('MapInfoWindow', () => { expect(infoWindowSpy.open).toHaveBeenCalledWith(mapSpy, fakeMarker); }); + it('should not try to reopen info window multiple times for the same marker', () => { + const fakeMarker = {} as unknown as google.maps.Marker; + const fakeMarkerComponent = { + marker: fakeMarker, + getAnchor: () => fakeMarker + } as unknown as MapMarker; + const infoWindowSpy = createInfoWindowSpy({}); + createInfoWindowConstructorSpy(infoWindowSpy).and.callThrough(); + + const fixture = TestBed.createComponent(TestApp); + const infoWindowComponent = fixture.debugElement.query(By.directive( + MapInfoWindow))!.injector.get(MapInfoWindow); + fixture.detectChanges(); + + infoWindowComponent.open(fakeMarkerComponent); + expect(infoWindowSpy.open).toHaveBeenCalledTimes(1); + + infoWindowComponent.open(fakeMarkerComponent); + expect(infoWindowSpy.open).toHaveBeenCalledTimes(1); + + infoWindowComponent.close(); + infoWindowComponent.open(fakeMarkerComponent); + expect(infoWindowSpy.open).toHaveBeenCalledTimes(2); + }); + it('exposes methods that provide information about the info window', () => { const infoWindowSpy = createInfoWindowSpy({}); createInfoWindowConstructorSpy(infoWindowSpy).and.callThrough(); diff --git a/src/google-maps/map-info-window/map-info-window.ts b/src/google-maps/map-info-window/map-info-window.ts index a2c46ace2a2b..15a94cbb9f59 100644 --- a/src/google-maps/map-info-window/map-info-window.ts +++ b/src/google-maps/map-info-window/map-info-window.ts @@ -173,8 +173,13 @@ export class MapInfoWindow implements OnInit, OnDestroy { */ open(anchor?: MapAnchorPoint) { this._assertInitialized(); - this._elementRef.nativeElement.style.display = ''; - this.infoWindow.open(this._googleMap.googleMap, anchor ? anchor.getAnchor() : undefined); + const anchorObject = anchor ? anchor.getAnchor() : undefined; + + // Prevent the info window from initializing if trying to reopen on the same anchor. + if (this.infoWindow.get('anchor') !== anchorObject) { + this._elementRef.nativeElement.style.display = ''; + this.infoWindow.open(this._googleMap.googleMap, anchorObject); + } } private _combineOptions(): Observable { diff --git a/src/google-maps/testing/fake-google-map-utils.ts b/src/google-maps/testing/fake-google-map-utils.ts index aa3e50603dc4..acaa99d763b4 100644 --- a/src/google-maps/testing/fake-google-map-utils.ts +++ b/src/google-maps/testing/fake-google-map-utils.ts @@ -93,10 +93,14 @@ export function createMarkerConstructorSpy(markerSpy: jasmine.SpyObj { + let anchor: any; const infoWindowSpy = jasmine.createSpyObj( 'google.maps.InfoWindow', - ['addListener', 'close', 'getContent', 'getPosition', 'getZIndex', 'open']); + ['addListener', 'close', 'getContent', 'getPosition', 'getZIndex', 'open', 'get']); infoWindowSpy.addListener.and.returnValue({remove: () => {}}); + infoWindowSpy.open.and.callFake((_map: any, target: any) => anchor = target); + infoWindowSpy.close.and.callFake(() => anchor = null); + infoWindowSpy.get.and.callFake((key: string) => key === 'anchor' ? anchor : null); return infoWindowSpy; }