@@ -22,10 +22,10 @@ import {
2222 Inject ,
2323 PLATFORM_ID ,
2424 NgZone ,
25+ SimpleChanges ,
2526} from '@angular/core' ;
2627import { isPlatformBrowser } from '@angular/common' ;
27- import { BehaviorSubject , combineLatest , Observable , Subject } from 'rxjs' ;
28- import { map , shareReplay , take , takeUntil } from 'rxjs/operators' ;
28+ import { Observable } from 'rxjs' ;
2929import { MapEventManager } from '../map-event-manager' ;
3030
3131interface GoogleMapsWindow extends Window {
@@ -57,13 +57,6 @@ export const DEFAULT_WIDTH = '500px';
5757} )
5858export class GoogleMap implements OnChanges , OnInit , OnDestroy {
5959 private _eventManager : MapEventManager = new MapEventManager ( this . _ngZone ) ;
60- private _googleMapChanges : Observable < google . maps . Map > ;
61-
62- private readonly _options = new BehaviorSubject < google . maps . MapOptions > ( DEFAULT_OPTIONS ) ;
63- private readonly _center =
64- new BehaviorSubject < google . maps . LatLngLiteral | google . maps . LatLng | undefined > ( undefined ) ;
65- private readonly _zoom = new BehaviorSubject < number | undefined > ( undefined ) ;
66- private readonly _destroy = new Subject < void > ( ) ;
6760 private _mapEl : HTMLElement ;
6861
6962 /**
@@ -90,16 +83,21 @@ export class GoogleMap implements OnChanges, OnInit, OnDestroy {
9083
9184 @Input ( )
9285 set center ( center : google . maps . LatLngLiteral | google . maps . LatLng ) {
93- this . _center . next ( center ) ;
86+ this . _center = center ;
9487 }
88+ private _center : google . maps . LatLngLiteral | google . maps . LatLng ;
89+
9590 @Input ( )
9691 set zoom ( zoom : number ) {
97- this . _zoom . next ( zoom ) ;
92+ this . _zoom = zoom ;
9893 }
94+ private _zoom : number ;
95+
9996 @Input ( )
10097 set options ( options : google . maps . MapOptions ) {
101- this . _options . next ( options || DEFAULT_OPTIONS ) ;
98+ this . _options = options || DEFAULT_OPTIONS ;
10299 }
100+ private _options = DEFAULT_OPTIONS ;
103101
104102 /**
105103 * See
@@ -246,10 +244,30 @@ export class GoogleMap implements OnChanges, OnInit, OnDestroy {
246244 }
247245 }
248246
249- ngOnChanges ( ) {
250- this . _setSize ( ) ;
251- if ( this . googleMap && this . mapTypeId ) {
252- this . googleMap . setMapTypeId ( this . mapTypeId ) ;
247+ ngOnChanges ( changes : SimpleChanges ) {
248+ if ( changes [ 'height' ] || changes [ 'width' ] ) {
249+ this . _setSize ( ) ;
250+ }
251+
252+ const googleMap = this . googleMap ;
253+
254+ if ( googleMap ) {
255+ if ( changes [ 'options' ] && this . _options ) {
256+ googleMap . setOptions ( this . _options ) ;
257+ }
258+
259+ if ( changes [ 'center' ] && this . _center ) {
260+ googleMap . setCenter ( this . _center ) ;
261+ }
262+
263+ // Note that the zoom can be zero.
264+ if ( changes [ 'zoom' ] && this . _zoom != null ) {
265+ googleMap . setZoom ( this . _zoom ) ;
266+ }
267+
268+ if ( changes [ 'mapTypeId' ] && this . mapTypeId ) {
269+ googleMap . setMapTypeId ( this . mapTypeId ) ;
270+ }
253271 }
254272 }
255273
@@ -258,22 +276,19 @@ export class GoogleMap implements OnChanges, OnInit, OnDestroy {
258276 if ( this . _isBrowser ) {
259277 this . _mapEl = this . _elementRef . nativeElement . querySelector ( '.map-container' ) ! ;
260278 this . _setSize ( ) ;
261- this . _googleMapChanges = this . _initializeMap ( this . _combineOptions ( ) ) ;
262- this . _googleMapChanges . subscribe ( ( googleMap : google . maps . Map ) => {
263- this . googleMap = googleMap ;
264- this . _eventManager . setTarget ( this . googleMap ) ;
265- } ) ;
266279
267- this . _watchForOptionsChanges ( ) ;
268- this . _watchForCenterChanges ( ) ;
269- this . _watchForZoomChanges ( ) ;
280+ // Create the object outside the zone so its events don't trigger change detection.
281+ // We'll bring it back in inside the `MapEventManager` only for the events that the
282+ // user has subscribed to.
283+ this . _ngZone . runOutsideAngular ( ( ) => {
284+ this . googleMap = new google . maps . Map ( this . _mapEl , this . _combineOptions ( ) ) ;
285+ } ) ;
286+ this . _eventManager . setTarget ( this . googleMap ) ;
270287 }
271288 }
272289
273290 ngOnDestroy ( ) {
274291 this . _eventManager . destroy ( ) ;
275- this . _destroy . next ( ) ;
276- this . _destroy . complete ( ) ;
277292 }
278293
279294 /**
@@ -443,60 +458,16 @@ export class GoogleMap implements OnChanges, OnInit, OnDestroy {
443458 }
444459
445460 /** Combines the center and zoom and the other map options into a single object */
446- private _combineOptions ( ) : Observable < google . maps . MapOptions > {
447- return combineLatest ( [ this . _options , this . _center , this . _zoom ] )
448- . pipe ( map ( ( [ options , center , zoom ] ) => {
449- const combinedOptions : google . maps . MapOptions = {
450- ...options ,
451- // It's important that we set **some** kind of `center` and `zoom`, otherwise
452- // Google Maps will render a blank rectangle which looks broken.
453- center : center || options . center || DEFAULT_OPTIONS . center ,
454- zoom : zoom ?? options . zoom ?? DEFAULT_OPTIONS . zoom ,
455- mapTypeId : this . mapTypeId
456- } ;
457- return combinedOptions ;
458- } ) ) ;
459- }
460-
461- private _initializeMap ( optionsChanges : Observable < google . maps . MapOptions > ) :
462- Observable < google . maps . Map > {
463- return optionsChanges . pipe (
464- take ( 1 ) ,
465- map ( options => {
466- // Create the object outside the zone so its events don't trigger change detection.
467- // We'll bring it back in inside the `MapEventManager` only for the events that the
468- // user has subscribed to.
469- return this . _ngZone . runOutsideAngular ( ( ) => new google . maps . Map ( this . _mapEl , options ) ) ;
470- } ) ,
471- shareReplay ( 1 ) ) ;
472- }
473-
474- private _watchForOptionsChanges ( ) {
475- combineLatest ( [ this . _googleMapChanges , this . _options ] )
476- . pipe ( takeUntil ( this . _destroy ) )
477- . subscribe ( ( [ googleMap , options ] ) => {
478- googleMap . setOptions ( options ) ;
479- } ) ;
480- }
481-
482- private _watchForCenterChanges ( ) {
483- combineLatest ( [ this . _googleMapChanges , this . _center ] )
484- . pipe ( takeUntil ( this . _destroy ) )
485- . subscribe ( ( [ googleMap , center ] ) => {
486- if ( center ) {
487- googleMap . setCenter ( center ) ;
488- }
489- } ) ;
490- }
491-
492- private _watchForZoomChanges ( ) {
493- combineLatest ( [ this . _googleMapChanges , this . _zoom ] )
494- . pipe ( takeUntil ( this . _destroy ) )
495- . subscribe ( ( [ googleMap , zoom ] ) => {
496- if ( zoom !== undefined ) {
497- googleMap . setZoom ( zoom ) ;
498- }
499- } ) ;
461+ private _combineOptions ( ) : google . maps . MapOptions {
462+ const options = this . _options ;
463+ return {
464+ ...options ,
465+ // It's important that we set **some** kind of `center` and `zoom`, otherwise
466+ // Google Maps will render a blank rectangle which looks broken.
467+ center : this . _center || options . center || DEFAULT_OPTIONS . center ,
468+ zoom : this . _zoom ?? options . zoom ?? DEFAULT_OPTIONS . zoom ,
469+ mapTypeId : this . mapTypeId
470+ } ;
500471 }
501472
502473 /** Asserts that the map has been initialized. */
0 commit comments