diff --git a/docs/content/guides/js-marker-clusterer/markers-cluster-with-js-marker-clusterer.md b/docs/content/guides/js-marker-clusterer/markers-cluster-with-js-marker-clusterer.md
index 21beb35da..6a0c58660 100644
--- a/docs/content/guides/js-marker-clusterer/markers-cluster-with-js-marker-clusterer.md
+++ b/docs/content/guides/js-marker-clusterer/markers-cluster-with-js-marker-clusterer.md
@@ -53,4 +53,16 @@ When you import the `AgmJsMarkerClustererModule`, you can use the `agmMarkerClus
-```
\ No newline at end of file
+```
+
+### Specifying a custom calculator
+
+If you want to control how the cluster style is calculated, you can pass in a `CalculateFunction` via `calculator`:
+
+```html
+
+
+
+
+
+```
diff --git a/packages/js-marker-clusterer/directives/marker-cluster.ts b/packages/js-marker-clusterer/directives/marker-cluster.ts
index 7af0be6a1..767ed33e8 100644
--- a/packages/js-marker-clusterer/directives/marker-cluster.ts
+++ b/packages/js-marker-clusterer/directives/marker-cluster.ts
@@ -3,7 +3,7 @@ import {Directive, Input, OnDestroy, OnChanges, OnInit, SimpleChange} from '@ang
import {ClusterManager} from '../services/managers/cluster-manager';
import {MarkerManager, InfoWindowManager} from '@agm/core';
-import {ClusterOptions, ClusterStyle} from '../services/google-clusterer-types';
+import {CalculateFunction, ClusterOptions, ClusterStyle} from '../services/google-clusterer-types';
/**
* AgmMarkerCluster clusters map marker if they are near together
@@ -71,6 +71,11 @@ export class AgmMarkerCluster implements OnDestroy, OnChanges, OnInit, ClusterOp
*/
@Input() styles: ClusterStyle;
+ /**
+ * A function that calculates the cluster style and text based on the markers in the cluster.
+ */
+ @Input() calculator: CalculateFunction;
+
@Input() imagePath: string;
@Input() imageExtension: string;
@@ -110,6 +115,9 @@ export class AgmMarkerCluster implements OnDestroy, OnChanges, OnInit, ClusterOp
if (changes['imageExtension']) {
this._clusterManager.setImageExtension(this);
}
+ if (changes['calculator']) {
+ this._clusterManager.setCalculator(this);
+ }
}
/** @internal */
diff --git a/packages/js-marker-clusterer/services/managers/cluster-manager.spec.ts b/packages/js-marker-clusterer/services/managers/cluster-manager.spec.ts
index aac2d61b8..b954e2f8d 100644
--- a/packages/js-marker-clusterer/services/managers/cluster-manager.spec.ts
+++ b/packages/js-marker-clusterer/services/managers/cluster-manager.spec.ts
@@ -3,7 +3,7 @@ import {TestBed, async, inject} from '@angular/core/testing';
import {AgmMarker} from '../../../core/directives/marker';
import {GoogleMapsAPIWrapper} from '../../../core/services/google-maps-api-wrapper';
-import {Marker} from '../../../core/services/google-maps-types';
+import {AgmMarkerCluster} from '../../directives/marker-cluster';
import {ClusterManager} from './cluster-manager';
describe('ClusterManager', () => {
@@ -207,4 +207,34 @@ describe('ClusterManager', () => {
() => { expect(markerInstance.setZIndex).toHaveBeenCalledWith(zIndex); });
})));
});
+
+ describe('set calculator', () => {
+ it('should call the setCalculator method when the calculator changes and is a function',
+ inject(
+ [ClusterManager],
+ async (markerManager: ClusterManager) => {
+
+ const mockClusterer = { setCalculator: jest.fn() };
+ const instancePromise = Promise.resolve(mockClusterer);
+
+ const spy = jest.spyOn(markerManager, 'getClustererInstance')
+ .mockImplementation(() => instancePromise);
+
+ const markerCluster: Partial = {};
+
+ // negative case
+ markerCluster.calculator = null;
+ markerManager.setCalculator(markerCluster as AgmMarkerCluster);
+ await instancePromise;
+ expect(mockClusterer.setCalculator).not.toHaveBeenCalled();
+
+ // positive case
+ markerCluster.calculator = jest.fn();
+ markerManager.setCalculator(markerCluster as AgmMarkerCluster);
+ await instancePromise;
+ expect(mockClusterer.setCalculator).toHaveBeenCalledTimes(1);
+
+ spy.mockRestore();
+ }));
+ });
});
diff --git a/packages/js-marker-clusterer/services/managers/cluster-manager.ts b/packages/js-marker-clusterer/services/managers/cluster-manager.ts
index 66feabf00..d063d72df 100644
--- a/packages/js-marker-clusterer/services/managers/cluster-manager.ts
+++ b/packages/js-marker-clusterer/services/managers/cluster-manager.ts
@@ -30,8 +30,12 @@ export class ClusterManager extends MarkerManager {
});
}
+ getClustererInstance(): Promise {
+ return this._clustererInstance;
+ }
+
addMarker(marker: AgmMarker): void {
- const clusterPromise: Promise = this._clustererInstance;
+ const clusterPromise: Promise = this.getClustererInstance();
const markerPromise = this._mapsWrapper
.createMarker({
position: {
@@ -65,7 +69,7 @@ export class ClusterManager extends MarkerManager {
return m.then((m: Marker) => {
this._zone.run(() => {
m.setMap(null);
- this._clustererInstance.then(cluster => {
+ this.getClustererInstance().then(cluster => {
cluster.removeMarker(m);
this._markers.delete(marker);
});
@@ -74,31 +78,31 @@ export class ClusterManager extends MarkerManager {
}
clearMarkers(): Promise {
- return this._clustererInstance.then(cluster => {
+ return this.getClustererInstance().then(cluster => {
cluster.clearMarkers();
});
}
setGridSize(c: AgmMarkerCluster): void {
- this._clustererInstance.then(cluster => {
+ this.getClustererInstance().then(cluster => {
cluster.setGridSize(c.gridSize);
});
}
setMaxZoom(c: AgmMarkerCluster): void {
- this._clustererInstance.then(cluster => {
+ this.getClustererInstance().then(cluster => {
cluster.setMaxZoom(c.maxZoom);
});
}
setStyles(c: AgmMarkerCluster): void {
- this._clustererInstance.then(cluster => {
+ this.getClustererInstance().then(cluster => {
cluster.setStyles(c.styles);
});
}
setZoomOnClick(c: AgmMarkerCluster): void {
- this._clustererInstance.then(cluster => {
+ this.getClustererInstance().then(cluster => {
if (c.zoomOnClick !== undefined) {
cluster.zoomOnClick_ = c.zoomOnClick;
}
@@ -106,7 +110,7 @@ export class ClusterManager extends MarkerManager {
}
setAverageCenter(c: AgmMarkerCluster): void {
- this._clustererInstance.then(cluster => {
+ this.getClustererInstance().then(cluster => {
if (c.averageCenter !== undefined) {
cluster.averageCenter_ = c.averageCenter;
}
@@ -114,7 +118,7 @@ export class ClusterManager extends MarkerManager {
}
setImagePath(c: AgmMarkerCluster): void {
- this._clustererInstance.then(cluster => {
+ this.getClustererInstance().then(cluster => {
if (c.imagePath !== undefined) {
cluster.imagePath_ = c.imagePath;
}
@@ -122,7 +126,7 @@ export class ClusterManager extends MarkerManager {
}
setMinimumClusterSize(c: AgmMarkerCluster): void {
- this._clustererInstance.then(cluster => {
+ this.getClustererInstance().then(cluster => {
if (c.minimumClusterSize !== undefined) {
cluster.minimumClusterSize_ = c.minimumClusterSize;
}
@@ -130,10 +134,18 @@ export class ClusterManager extends MarkerManager {
}
setImageExtension(c: AgmMarkerCluster): void {
- this._clustererInstance.then(cluster => {
+ this.getClustererInstance().then(cluster => {
if (c.imageExtension !== undefined) {
cluster.imageExtension_ = c.imageExtension;
}
});
}
+
+ setCalculator (c: AgmMarkerCluster): void {
+ this.getClustererInstance().then(cluster => {
+ if (typeof c.calculator === 'function') {
+ cluster.setCalculator(c.calculator);
+ }
+ });
+ }
}