diff --git a/src/google-maps/map-marker-clusterer/map-marker-clusterer.ts b/src/google-maps/map-marker-clusterer/map-marker-clusterer.ts index 48655a63b8e2..67088b701032 100644 --- a/src/google-maps/map-marker-clusterer/map-marker-clusterer.ts +++ b/src/google-maps/map-marker-clusterer/map-marker-clusterer.ts @@ -17,14 +17,16 @@ import { ContentChildren, Input, NgZone, + OnChanges, OnDestroy, OnInit, Output, QueryList, + SimpleChanges, ViewEncapsulation } from '@angular/core'; -import {BehaviorSubject, combineLatest, Observable, Subject} from 'rxjs'; -import {map, take, takeUntil} from 'rxjs/operators'; +import {Observable, Subject} from 'rxjs'; +import {takeUntil} from 'rxjs/operators'; import {GoogleMap} from '../google-map/google-map'; import {MapEventManager} from '../map-event-manager'; @@ -42,27 +44,8 @@ import {MapMarker} from '../map-marker/map-marker'; template: '', encapsulation: ViewEncapsulation.None, }) -export class MapMarkerClusterer implements OnInit, AfterContentInit, OnDestroy { - private readonly _ariaLabelFn = new BehaviorSubject(undefined); - private readonly _averageCenter = new BehaviorSubject(undefined); - private readonly _batchSizeIE = new BehaviorSubject(undefined); - private readonly _calculator = new BehaviorSubject(undefined); - private readonly _clusterClass = new BehaviorSubject(undefined); - private readonly _enableRetinaIcons = new BehaviorSubject(undefined); - private readonly _gridSize = new BehaviorSubject(undefined); - private readonly _ignoreHidden = new BehaviorSubject(undefined); - private readonly _imageExtension = new BehaviorSubject(undefined); - private readonly _imagePath = new BehaviorSubject(undefined); - private readonly _imageSizes = new BehaviorSubject(undefined); - private readonly _maxZoom = new BehaviorSubject(undefined); - private readonly _minimumClusterSize = new BehaviorSubject(undefined); - private readonly _styles = new BehaviorSubject(undefined); - private readonly _title = new BehaviorSubject(undefined); - private readonly _zIndex = new BehaviorSubject(undefined); - private readonly _zoomOnClick = new BehaviorSubject(undefined); - +export class MapMarkerClusterer implements OnInit, AfterContentInit, OnChanges, OnDestroy { private readonly _currentMarkers = new Set(); - private readonly _eventManager = new MapEventManager(this._ngZone); private readonly _destroy = new Subject(); @@ -70,94 +53,105 @@ export class MapMarkerClusterer implements OnInit, AfterContentInit, OnDestroy { private readonly _canInitialize: boolean; @Input() - get ariaLabelFn(): AriaLabelFn { - return this.markerClusterer ? this.markerClusterer.ariaLabelFn : () => ''; - } - set ariaLabelFn(ariaLabelFn: AriaLabelFn) { - this._ariaLabelFn.next(ariaLabelFn); - } + ariaLabelFn: AriaLabelFn = () => '' @Input() set averageCenter(averageCenter: boolean) { - this._averageCenter.next(averageCenter); + this._averageCenter = averageCenter; } + private _averageCenter: boolean; @Input() batchSize?: number; @Input() set batchSizeIE(batchSizeIE: number) { - this._batchSizeIE.next(batchSizeIE); + this._batchSizeIE = batchSizeIE; } + private _batchSizeIE: number; @Input() set calculator(calculator: Calculator) { - this._calculator.next(calculator); + this._calculator = calculator; } + private _calculator: Calculator; @Input() set clusterClass(clusterClass: string) { - this._clusterClass.next(clusterClass); + this._clusterClass = clusterClass; } + private _clusterClass: string; @Input() set enableRetinaIcons(enableRetinaIcons: boolean) { - this._enableRetinaIcons.next(enableRetinaIcons); + this._enableRetinaIcons = enableRetinaIcons; } + private _enableRetinaIcons: boolean; @Input() set gridSize(gridSize: number) { - this._gridSize.next(gridSize); + this._gridSize = gridSize; } + private _gridSize: number; @Input() set ignoreHidden(ignoreHidden: boolean) { - this._ignoreHidden.next(ignoreHidden); + this._ignoreHidden = ignoreHidden; } + private _ignoreHidden: boolean; @Input() set imageExtension(imageExtension: string) { - this._imageExtension.next(imageExtension); + this._imageExtension = imageExtension; } + private _imageExtension: string; @Input() set imagePath(imagePath: string) { - this._imagePath.next(imagePath); + this._imagePath = imagePath; } + private _imagePath: string; @Input() set imageSizes(imageSizes: number[]) { - this._imageSizes.next(imageSizes); + this._imageSizes = imageSizes; } + private _imageSizes: number[]; @Input() set maxZoom(maxZoom: number) { - this._maxZoom.next(maxZoom); + this._maxZoom = maxZoom; } + private _maxZoom: number; @Input() set minimumClusterSize(minimumClusterSize: number) { - this._minimumClusterSize.next(minimumClusterSize); + this._minimumClusterSize = minimumClusterSize; } + private _minimumClusterSize: number; @Input() set styles(styles: ClusterIconStyle[]) { - this._styles.next(styles); + this._styles = styles; } + private _styles: ClusterIconStyle[]; @Input() set title(title: string) { - this._title.next(title); + this._title = title; } + private _title: string; @Input() set zIndex(zIndex: number) { - this._zIndex.next(zIndex); + this._zIndex = zIndex; } + private _zIndex: number; @Input() set zoomOnClick(zoomOnClick: boolean) { - this._zoomOnClick.next(zoomOnClick); + this._zoomOnClick = zoomOnClick; } + private _zoomOnClick: boolean; /** * See @@ -191,35 +185,16 @@ export class MapMarkerClusterer implements OnInit, AfterContentInit, OnDestroy { ngOnInit() { if (this._canInitialize) { - this._combineOptions().pipe(take(1)).subscribe(options => { - // Create the object outside the zone so its events don't trigger change detection. - // We'll bring it back in inside the `MapEventManager` only for the events that the - // user has subscribed to. - this._ngZone.runOutsideAngular(() => { - this.markerClusterer = new MarkerClusterer(this._googleMap.googleMap!, [], options); - }); - - this._assertInitialized(); - this._eventManager.setTarget(this.markerClusterer); + // Create the object outside the zone so its events don't trigger change detection. + // We'll bring it back in inside the `MapEventManager` only for the events that the + // user has subscribed to. + this._ngZone.runOutsideAngular(() => { + this.markerClusterer = new MarkerClusterer(this._googleMap.googleMap!, [], + this._combineOptions()); }); - this._watchForAriaLabelFnChanges(); - this._watchForAverageCenterChanges(); - this._watchForBatchSizeIEChanges(); - this._watchForCalculatorChanges(); - this._watchForClusterClassChanges(); - this._watchForEnableRetinaIconsChanges(); - this._watchForGridSizeChanges(); - this._watchForIgnoreHiddenChanges(); - this._watchForImageExtensionChanges(); - this._watchForImagePathChanges(); - this._watchForImageSizesChanges(); - this._watchForMaxZoomChanges(); - this._watchForMinimumClusterSizeChanges(); - this._watchForStylesChanges(); - this._watchForTitleChanges(); - this._watchForZIndexChanges(); - this._watchForZoomOnClickChanges(); + this._assertInitialized(); + this._eventManager.setTarget(this.markerClusterer); } } @@ -229,6 +204,68 @@ export class MapMarkerClusterer implements OnInit, AfterContentInit, OnDestroy { } } + ngOnChanges(changes: SimpleChanges) { + const { + markerClusterer: clusterer, ariaLabelFn, _averageCenter, _batchSizeIE, _calculator, _styles, + _clusterClass, _enableRetinaIcons, _gridSize, _ignoreHidden, _imageExtension, _imagePath, + _imageSizes, _maxZoom, _minimumClusterSize, _title, _zIndex, _zoomOnClick + } = this; + + if (clusterer) { + if (changes['ariaLabelFn']) { + clusterer.ariaLabelFn = ariaLabelFn; + } + if (changes['averageCenter'] && _averageCenter !== undefined) { + clusterer.setAverageCenter(_averageCenter); + } + if (changes['batchSizeIE'] && _batchSizeIE !== undefined) { + clusterer.setBatchSizeIE(_batchSizeIE); + } + if (changes['calculator'] && _calculator) { + clusterer.setCalculator(_calculator); + } + if (changes['clusterClass'] && _clusterClass !== undefined) { + clusterer.setClusterClass(_clusterClass); + } + if (changes['enableRetinaIcons'] && _enableRetinaIcons !== undefined) { + clusterer.setEnableRetinaIcons(_enableRetinaIcons); + } + if (changes['gridSize'] && _gridSize !== undefined) { + clusterer.setGridSize(_gridSize); + } + if (changes['ignoreHidden'] && _ignoreHidden !== undefined) { + clusterer.setIgnoreHidden(_ignoreHidden); + } + if (changes['imageExtension'] && _imageExtension !== undefined) { + clusterer.setImageExtension(_imageExtension); + } + if (changes['imagePath'] && _imagePath !== undefined) { + clusterer.setImagePath(_imagePath); + } + if (changes['imageSizes'] && _imageSizes) { + clusterer.setImageSizes(_imageSizes); + } + if (changes['maxZoom'] && _maxZoom !== undefined) { + clusterer.setMaxZoom(_maxZoom); + } + if (changes['minimumClusterSize'] && _minimumClusterSize !== undefined) { + clusterer.setMinimumClusterSize(_minimumClusterSize); + } + if (changes['styles'] && _styles) { + clusterer.setStyles(_styles); + } + if (changes['title'] && _title !== undefined) { + clusterer.setTitle(_title); + } + if (changes['zIndex'] && _zIndex !== undefined) { + clusterer.setZIndex(_zIndex); + } + if (changes['zoomOnClick'] && _zoomOnClick !== undefined) { + clusterer.setZoomOnClick(_zoomOnClick); + } + } + } + ngOnDestroy() { this._destroy.next(); this._destroy.complete(); @@ -338,219 +375,27 @@ export class MapMarkerClusterer implements OnInit, AfterContentInit, OnDestroy { return this.markerClusterer.getZoomOnClick(); } - private _combineOptions(): Observable { - return combineLatest([ - this._ariaLabelFn, - this._averageCenter, - this._batchSizeIE, - this._calculator, - this._clusterClass, - this._enableRetinaIcons, - this._gridSize, - this._ignoreHidden, - this._imageExtension, - this._imagePath, - this._imageSizes, - this._maxZoom, - this._minimumClusterSize, - this._styles, - this._title, - this._zIndex, - this._zoomOnClick, - ]).pipe(take(1), map(([ - ariaLabelFn, - averageCenter, - batchSizeIE, - calculator, - clusterClass, - enableRetinaIcons, - gridSize, - ignoreHidden, - imageExtension, - imagePath, - imageSizes, - maxZoom, - minimumClusterSize, - styles, - title, - zIndex, - zoomOnClick, - ]) => { - const combinedOptions: MarkerClustererOptions = { - ariaLabelFn: ariaLabelFn as AriaLabelFn|undefined, - averageCenter: averageCenter as boolean|undefined, - batchSize: this.batchSize, - batchSizeIE: batchSizeIE as number|undefined, - calculator: calculator as Calculator|undefined, - clusterClass: clusterClass as string|undefined, - enableRetinaIcons: enableRetinaIcons as boolean|undefined, - gridSize: gridSize as number|undefined, - ignoreHidden: ignoreHidden as boolean|undefined, - imageExtension: imageExtension as string|undefined, - imagePath: imagePath as string|undefined, - imageSizes: imageSizes as number[]|undefined, - maxZoom: maxZoom as number|undefined, - minimumClusterSize: minimumClusterSize as number|undefined, - styles: styles as ClusterIconStyle[]|undefined, - title: title as string|undefined, - zIndex: zIndex as number|undefined, - zoomOnClick: zoomOnClick as boolean|undefined, - }; - return combinedOptions; - })); - } - - private _watchForAriaLabelFnChanges() { - this._ariaLabelFn.pipe(takeUntil(this._destroy)).subscribe(ariaLabelFn => { - if (this.markerClusterer && ariaLabelFn) { - this._assertInitialized(); - this.markerClusterer.ariaLabelFn = ariaLabelFn; - } - }); - } - - private _watchForAverageCenterChanges() { - this._averageCenter.pipe(takeUntil(this._destroy)).subscribe(averageCenter => { - if (this.markerClusterer && averageCenter !== undefined) { - this._assertInitialized(); - this.markerClusterer.setAverageCenter(averageCenter); - } - }); - } - - private _watchForBatchSizeIEChanges() { - this._batchSizeIE.pipe(takeUntil(this._destroy)).subscribe(batchSizeIE => { - if (this.markerClusterer && batchSizeIE !== undefined) { - this._assertInitialized(); - this.markerClusterer.setBatchSizeIE(batchSizeIE); - } - }); - } - - private _watchForCalculatorChanges() { - this._calculator.pipe(takeUntil(this._destroy)).subscribe(calculator => { - if (this.markerClusterer && calculator) { - this._assertInitialized(); - this.markerClusterer.setCalculator(calculator); - } - }); - } - - private _watchForClusterClassChanges() { - this._clusterClass.pipe(takeUntil(this._destroy)).subscribe(clusterClass => { - if (this.markerClusterer && clusterClass !== undefined) { - this._assertInitialized(); - this.markerClusterer.setClusterClass(clusterClass); - } - }); - } - - private _watchForEnableRetinaIconsChanges() { - this._enableRetinaIcons.pipe(takeUntil(this._destroy)).subscribe(enableRetinaIcons => { - if (this.markerClusterer && enableRetinaIcons !== undefined) { - this._assertInitialized(); - this.markerClusterer.setEnableRetinaIcons(enableRetinaIcons); - } - }); - } - - private _watchForGridSizeChanges() { - this._gridSize.pipe(takeUntil(this._destroy)).subscribe(gridSize => { - if (this.markerClusterer && gridSize !== undefined) { - this._assertInitialized(); - this.markerClusterer.setGridSize(gridSize); - } - }); - } - - private _watchForIgnoreHiddenChanges() { - this._ignoreHidden.pipe(takeUntil(this._destroy)).subscribe(ignoreHidden => { - if (this.markerClusterer && ignoreHidden !== undefined) { - this._assertInitialized(); - this.markerClusterer.setIgnoreHidden(ignoreHidden); - } - }); - } - - private _watchForImageExtensionChanges() { - this._imageExtension.pipe(takeUntil(this._destroy)).subscribe(imageExtension => { - if (this.markerClusterer && imageExtension !== undefined) { - this._assertInitialized(); - this.markerClusterer.setImageExtension(imageExtension); - } - }); - } - - private _watchForImagePathChanges() { - this._imagePath.pipe(takeUntil(this._destroy)).subscribe(imagePath => { - if (this.markerClusterer && imagePath !== undefined) { - this._assertInitialized(); - this.markerClusterer.setImagePath(imagePath); - } - }); - } - - private _watchForImageSizesChanges() { - this._imageSizes.pipe(takeUntil(this._destroy)).subscribe(imageSizes => { - if (this.markerClusterer && imageSizes) { - this._assertInitialized(); - this.markerClusterer.setImageSizes(imageSizes); - } - }); - } - - private _watchForMaxZoomChanges() { - this._maxZoom.pipe(takeUntil(this._destroy)).subscribe(maxZoom => { - if (this.markerClusterer && maxZoom !== undefined) { - this._assertInitialized(); - this.markerClusterer.setMaxZoom(maxZoom); - } - }); - } - - private _watchForMinimumClusterSizeChanges() { - this._minimumClusterSize.pipe(takeUntil(this._destroy)).subscribe(minimumClusterSize => { - if (this.markerClusterer && minimumClusterSize !== undefined) { - this._assertInitialized(); - this.markerClusterer.setMinimumClusterSize(minimumClusterSize); - } - }); - } - - private _watchForStylesChanges() { - this._styles.pipe(takeUntil(this._destroy)).subscribe(styles => { - if (this.markerClusterer && styles) { - this._assertInitialized(); - this.markerClusterer.setStyles(styles); - } - }); - } - - private _watchForTitleChanges() { - this._title.pipe(takeUntil(this._destroy)).subscribe(title => { - if (this.markerClusterer && title !== undefined) { - this._assertInitialized(); - this.markerClusterer.setTitle(title); - } - }); - } - - private _watchForZIndexChanges() { - this._zIndex.pipe(takeUntil(this._destroy)).subscribe(zIndex => { - if (this.markerClusterer && zIndex !== undefined) { - this._assertInitialized(); - this.markerClusterer.setZIndex(zIndex); - } - }); - } - - private _watchForZoomOnClickChanges() { - this._zoomOnClick.pipe(takeUntil(this._destroy)).subscribe(zoomOnClick => { - if (this.markerClusterer && zoomOnClick !== undefined) { - this._assertInitialized(); - this.markerClusterer.setZoomOnClick(zoomOnClick); - } - }); + private _combineOptions(): MarkerClustererOptions { + return { + ariaLabelFn: this.ariaLabelFn, + averageCenter: this._averageCenter, + batchSize: this.batchSize, + batchSizeIE: this._batchSizeIE, + calculator: this._calculator, + clusterClass: this._clusterClass, + enableRetinaIcons: this._enableRetinaIcons, + gridSize: this._gridSize, + ignoreHidden: this._ignoreHidden, + imageExtension: this._imageExtension, + imagePath: this._imagePath, + imageSizes: this._imageSizes, + maxZoom: this._maxZoom, + minimumClusterSize: this._minimumClusterSize, + styles: this._styles, + title: this._title, + zIndex: this._zIndex, + zoomOnClick: this._zoomOnClick, + }; } private _watchForMarkerChanges() { diff --git a/tools/public_api_guard/google-maps/google-maps.d.ts b/tools/public_api_guard/google-maps/google-maps.d.ts index 33ccbfa959f3..cd94f645f9f6 100644 --- a/tools/public_api_guard/google-maps/google-maps.d.ts +++ b/tools/public_api_guard/google-maps/google-maps.d.ts @@ -220,10 +220,9 @@ export declare class MapMarker implements OnInit, OnChanges, OnDestroy, MapAncho static ɵfac: i0.ɵɵFactoryDef; } -export declare class MapMarkerClusterer implements OnInit, AfterContentInit, OnDestroy { +export declare class MapMarkerClusterer implements OnInit, AfterContentInit, OnChanges, OnDestroy { _markers: QueryList; - get ariaLabelFn(): AriaLabelFn; - set ariaLabelFn(ariaLabelFn: AriaLabelFn); + ariaLabelFn: AriaLabelFn; set averageCenter(averageCenter: boolean); batchSize?: number; set batchSizeIE(batchSizeIE: number); @@ -266,6 +265,7 @@ export declare class MapMarkerClusterer implements OnInit, AfterContentInit, OnD getZIndex(): number; getZoomOnClick(): boolean; ngAfterContentInit(): void; + ngOnChanges(changes: SimpleChanges): void; ngOnDestroy(): void; ngOnInit(): void; static ɵcmp: i0.ɵɵComponentDefWithMeta;