bluehalo / ngx-leaflet-markercluster

MIT License
61 stars 24 forks source link

TypeError: L.markerClusterGroup is not a function #88

Closed javanese84 closed 7 months ago

javanese84 commented 7 months ago

Hi,

I just tried implementing the markerCluster functionality into my application based on Angular17 (with standalone Components). I copied the example from this repo 1:1 (as own module as in the example) and getting the following error: TypeError: L.markerClusterGroup is not a function image

The Error is thrown within the directive in the ngOnInit (line 18). See the following screenshot.

image

Extract from package.json: "leaflet": "^1.9.4", "leaflet.markercluster": "^1.5.3", "@asymmetrik/ngx-leaflet": "^17.0.0", "@asymmetrik/ngx-leaflet-markercluster": "^17.0.0",

javanese84 commented 7 months ago

Now, it works without any issue. That's my code:

const markerArray = L.markerClusterGroup();
for (const loc of this.locations) {
  passArray.addLayer(marker([ loc.lat, loc.lon ], {
    icon: this.icon
  }));
}
this.markerGroup = markerArray;

in my template:

<div style="height: 500px;"
       leaflet
       (leafletMapReady)="onMapReady($event)"
       [leafletOptions]="options">
    @if (markerGroup) {
      <div [leafletLayer]="markerGroup"></div>
    }
</div>
buravlev-arthur commented 1 month ago

I've come across this issue too. I solved this problem by next steps:

  1. Add leaflet and leaflet.markercluster scripts in a “scripts” array (angular.json), in the current order:

    "scripts": [
    "node_modules/leaflet/dist/leaflet.js",
    "node_modules/leaflet.markercluster/dist/leaflet.markercluster.js"
    ];
  2. These scripts will add “L” object as a field of the global “window” object. Now you can get Leaflet extended by “markercluster” plugin as: window.L anywhere;

  3. Define a private field (“leaflet” in my case) in component/directive/services classes, where you use Leaflet:

import 'leaflet.markercluster'; // you need import this locally anyway for "markercluster" methods ts-declaration

@Component({}) export class AppComponent() { private leaflet = window.L; // here is our leaflet with the clusters

initMap() { const map = this.leaflet.map('map').setView([0, 0], 10); const markers = this.leaflet.markerClusterGroup(); // now this method is defined! map.addLayer(markers); } }


Works for me on Angular 18.2.0.
q-stefanorzu commented 2 weeks ago

Having the same issue here. I think this problem would go away if the import to Leaflet inside LeafletMarkerClusterDirective would be

import L from 'leaflet`

I'm currently migrating a project from Angular 15 to 18 and I started encountering the "not a constructor" error wherever a constructor from a leaflet plugin was being initialised, e.g. new L.StripePattern({...}). This is due to how the newer version of Angular bundles Leaflet - at runtime L resolves to {default: <the actual Leaflet object>, <...core Leaflet functions>}. Changing the import to the above notation worked for me, so I reckon this directive needs to follow the same approach.