9
9
// Workaround for: https://github.com/bazelbuild/rules_nodejs/issues/1265
10
10
/// <reference types="googlemaps" />
11
11
12
- import { Input , OnDestroy , OnInit , Output , NgZone , Directive } from '@angular/core' ;
13
- import { BehaviorSubject , combineLatest , Observable , Subject } from 'rxjs' ;
14
- import { map , take , takeUntil } from 'rxjs/operators' ;
12
+ import {
13
+ Input ,
14
+ OnDestroy ,
15
+ OnInit ,
16
+ Output ,
17
+ NgZone ,
18
+ Directive ,
19
+ OnChanges ,
20
+ SimpleChanges ,
21
+ } from '@angular/core' ;
22
+ import { Observable } from 'rxjs' ;
15
23
16
24
import { GoogleMap } from '../google-map/google-map' ;
17
25
import { MapEventManager } from '../map-event-manager' ;
@@ -34,42 +42,58 @@ export const DEFAULT_MARKER_OPTIONS = {
34
42
selector : 'map-marker' ,
35
43
exportAs : 'mapMarker' ,
36
44
} )
37
- export class MapMarker implements OnInit , OnDestroy , MapAnchorPoint {
45
+ export class MapMarker implements OnInit , OnChanges , OnDestroy , MapAnchorPoint {
38
46
private _eventManager = new MapEventManager ( this . _ngZone ) ;
39
- private readonly _options =
40
- new BehaviorSubject < google . maps . MarkerOptions > ( DEFAULT_MARKER_OPTIONS ) ;
41
- private readonly _title = new BehaviorSubject < string | undefined > ( undefined ) ;
42
- private readonly _position =
43
- new BehaviorSubject < google . maps . LatLngLiteral | google . maps . LatLng | undefined > ( undefined ) ;
44
- private readonly _label =
45
- new BehaviorSubject < string | google . maps . MarkerLabel | undefined > ( undefined ) ;
46
- private readonly _clickable = new BehaviorSubject < boolean | undefined > ( undefined ) ;
47
- private readonly _destroy = new Subject < void > ( ) ;
48
-
49
- @Input ( )
50
- set options ( options : google . maps . MarkerOptions ) {
51
- this . _options . next ( options || DEFAULT_MARKER_OPTIONS ) ;
52
- }
53
47
48
+ /**
49
+ * Title of the marker.
50
+ * See: developers.google.com/maps/documentation/javascript/reference/marker#MarkerOptions.title
51
+ */
54
52
@Input ( )
55
53
set title ( title : string ) {
56
- this . _title . next ( title ) ;
54
+ this . _title = title ;
57
55
}
56
+ private _title : string ;
58
57
58
+ /**
59
+ * Title of the marker. See:
60
+ * developers.google.com/maps/documentation/javascript/reference/marker#MarkerOptions.position
61
+ */
59
62
@Input ( )
60
63
set position ( position : google . maps . LatLngLiteral | google . maps . LatLng ) {
61
- this . _position . next ( position ) ;
64
+ this . _position = position ;
62
65
}
66
+ private _position : google . maps . LatLngLiteral | google . maps . LatLng ;
63
67
68
+ /**
69
+ * Label for the marker.
70
+ * See: developers.google.com/maps/documentation/javascript/reference/marker#MarkerOptions.label
71
+ */
64
72
@Input ( )
65
73
set label ( label : string | google . maps . MarkerLabel ) {
66
- this . _label . next ( label ) ;
74
+ this . _label = label ;
67
75
}
76
+ private _label : string | google . maps . MarkerLabel ;
68
77
78
+ /**
79
+ * Whether the marker is clickable. See:
80
+ * developers.google.com/maps/documentation/javascript/reference/marker#MarkerOptions.clickable
81
+ */
69
82
@Input ( )
70
83
set clickable ( clickable : boolean ) {
71
- this . _clickable . next ( clickable ) ;
84
+ this . _clickable = clickable ;
72
85
}
86
+ private _clickable : boolean ;
87
+
88
+ /**
89
+ * Options used to configure the marker.
90
+ * See: developers.google.com/maps/documentation/javascript/reference/marker#MarkerOptions
91
+ */
92
+ @Input ( )
93
+ set options ( options : google . maps . MarkerOptions ) {
94
+ this . _options = options ;
95
+ }
96
+ private _options : google . maps . MarkerOptions ;
73
97
74
98
/**
75
99
* See
@@ -239,27 +263,45 @@ export class MapMarker implements OnInit, OnDestroy, MapAnchorPoint {
239
263
240
264
ngOnInit ( ) {
241
265
if ( this . _googleMap . _isBrowser ) {
242
- this . _combineOptions ( ) . pipe ( take ( 1 ) ) . subscribe ( options => {
243
- // Create the object outside the zone so its events don't trigger change detection.
244
- // We'll bring it back in inside the `MapEventManager` only for the events that the
245
- // user has subscribed to.
246
- this . _ngZone . runOutsideAngular ( ( ) => this . marker = new google . maps . Marker ( options ) ) ;
247
- this . _assertInitialized ( ) ;
248
- this . marker . setMap ( this . _googleMap . googleMap ! ) ;
249
- this . _eventManager . setTarget ( this . marker ) ;
266
+ // Create the object outside the zone so its events don't trigger change detection.
267
+ // We'll bring it back in inside the `MapEventManager` only for the events that the
268
+ // user has subscribed to.
269
+ this . _ngZone . runOutsideAngular ( ( ) => {
270
+ this . marker = new google . maps . Marker ( this . _combineOptions ( ) ) ;
250
271
} ) ;
272
+ this . _assertInitialized ( ) ;
273
+ this . marker . setMap ( this . _googleMap . googleMap ! ) ;
274
+ this . _eventManager . setTarget ( this . marker ) ;
275
+ }
276
+ }
277
+
278
+ ngOnChanges ( changes : SimpleChanges ) {
279
+ const { marker, _title, _position, _label, _clickable} = this ;
280
+
281
+ if ( marker ) {
282
+ if ( changes . options ) {
283
+ marker . setOptions ( this . _combineOptions ( ) ) ;
284
+ }
251
285
252
- this . _watchForOptionsChanges ( ) ;
253
- this . _watchForTitleChanges ( ) ;
254
- this . _watchForPositionChanges ( ) ;
255
- this . _watchForLabelChanges ( ) ;
256
- this . _watchForClickableChanges ( ) ;
286
+ if ( changes . title && _title !== undefined ) {
287
+ marker . setTitle ( _title ) ;
288
+ }
289
+
290
+ if ( changes . position && _position ) {
291
+ marker . setPosition ( _position ) ;
292
+ }
293
+
294
+ if ( changes . label && _label !== undefined ) {
295
+ marker . setLabel ( _label ) ;
296
+ }
297
+
298
+ if ( changes . clickable && _clickable !== undefined ) {
299
+ marker . setClickable ( _clickable ) ;
300
+ }
257
301
}
258
302
}
259
303
260
304
ngOnDestroy ( ) {
261
- this . _destroy . next ( ) ;
262
- this . _destroy . complete ( ) ;
263
305
this . _eventManager . destroy ( ) ;
264
306
if ( this . marker ) {
265
307
this . marker . setMap ( null ) ;
@@ -380,64 +422,17 @@ export class MapMarker implements OnInit, OnDestroy, MapAnchorPoint {
380
422
return this . marker ;
381
423
}
382
424
383
- private _combineOptions ( ) : Observable < google . maps . MarkerOptions > {
384
- return combineLatest ( [ this . _options , this . _title , this . _position , this . _label , this . _clickable ] )
385
- . pipe ( map ( ( [ options , title , position , label , clickable ] ) => {
386
- const combinedOptions : google . maps . MarkerOptions = {
387
- ...options ,
388
- title : title || options . title ,
389
- position : position || options . position ,
390
- label : label || options . label ,
391
- clickable : clickable !== undefined ? clickable : options . clickable ,
392
- map : this . _googleMap . googleMap ,
393
- } ;
394
- return combinedOptions ;
395
- } ) ) ;
396
- }
397
-
398
- private _watchForOptionsChanges ( ) {
399
- this . _options . pipe ( takeUntil ( this . _destroy ) ) . subscribe ( options => {
400
- if ( this . marker ) {
401
- this . _assertInitialized ( ) ;
402
- this . marker . setOptions ( options ) ;
403
- }
404
- } ) ;
405
- }
406
-
407
- private _watchForTitleChanges ( ) {
408
- this . _title . pipe ( takeUntil ( this . _destroy ) ) . subscribe ( title => {
409
- if ( this . marker && title !== undefined ) {
410
- this . _assertInitialized ( ) ;
411
- this . marker . setTitle ( title ) ;
412
- }
413
- } ) ;
414
- }
415
-
416
- private _watchForPositionChanges ( ) {
417
- this . _position . pipe ( takeUntil ( this . _destroy ) ) . subscribe ( position => {
418
- if ( this . marker && position ) {
419
- this . _assertInitialized ( ) ;
420
- this . marker . setPosition ( position ) ;
421
- }
422
- } ) ;
423
- }
424
-
425
- private _watchForLabelChanges ( ) {
426
- this . _label . pipe ( takeUntil ( this . _destroy ) ) . subscribe ( label => {
427
- if ( this . marker && label !== undefined ) {
428
- this . _assertInitialized ( ) ;
429
- this . marker . setLabel ( label ) ;
430
- }
431
- } ) ;
432
- }
433
-
434
- private _watchForClickableChanges ( ) {
435
- this . _clickable . pipe ( takeUntil ( this . _destroy ) ) . subscribe ( clickable => {
436
- if ( this . marker && clickable !== undefined ) {
437
- this . _assertInitialized ( ) ;
438
- this . marker . setClickable ( clickable ) ;
439
- }
440
- } ) ;
425
+ /** Creates a combined options object using the passed-in options and the individual inputs. */
426
+ private _combineOptions ( ) : google . maps . MarkerOptions {
427
+ const options = this . _options || DEFAULT_MARKER_OPTIONS ;
428
+ return {
429
+ ...options ,
430
+ title : this . _title || options . title ,
431
+ position : this . _position || options . position ,
432
+ label : this . _label || options . label ,
433
+ clickable : this . _clickable !== undefined ? this . _clickable : options . clickable ,
434
+ map : this . _googleMap . googleMap ,
435
+ } ;
441
436
}
442
437
443
438
private _assertInitialized ( ) : asserts this is { marker : google . maps . Marker } {
0 commit comments