Cheat Bot
Cheat Bot

Reputation: 23

Svelte and Leaflet plugins not importing correctly

I want to add various plugins to leaflet, such as: leaflet.markercluster.
On the internet I found an example to make leaflet work on svelte and I noticed that leaflet is imported via an asynchronous function.

This is my Map.svelte component:

<script>
    import { onMount, onDestroy } from 'svelte';
    import { browser } from '$app/environment';

    let mapElement;
    let map;
    let markers = [
        { lat: 51.5, lng: -0.09, popupText: 'a' },
        { lat: 51.51, lng: -0.1, popupText: 'b' },

    ];

    onMount(async () => {
        if (browser) {
            const leaflet = await import('leaflet');
            await import('leaflet.markercluster');

            map = leaflet.map(mapElement).setView([51.505, -0.09], 13);

            leaflet.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
                attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
            }).addTo(map);

            // Create marker cluster group
            const markerClusterGroup = leaflet.markerClusterGroup();
            
            // Loop through the markers array and create individual markers
            markers.forEach(marker => {
                const { lat, lng, popupText } = marker;
                const individualMarker = leaflet.marker([lat, lng]).bindPopup(popupText);
                markerClusterGroup.addLayer(individualMarker);
            });

            // Add the cluster group to the map
            map.addLayer(markerClusterGroup);
        }
    });

    onDestroy(async () => {
        if (map) {
            console.log('Unloading Leaflet map.');
            map.remove();
        }
    });
</script>


<main>
    <div bind:this={mapElement}></div>
</main>

<style>
    @import 'leaflet/dist/leaflet.css';
    @import 'leaflet.markercluster/dist/MarkerCluster.css';
    @import 'leaflet.markercluster/dist/MarkerCluster.Default.css';
    main div {
        height: 800px;
    }
</style>

When I try to do the same thing with leaflet.markercluster it doesn't work. What am I doing wrong?

Edit:

I tried inserting the {#await} block but it doesn't change anything. Now the +page.svelt

<script>
    import Map from "./Map.svelte";
</script>

<h1>Mappona</h1>
{#await Map}
    Loading...
{:then Map}
    <Map />
{/await} 

Error: Uncaught (in promise) TypeError: leaflet.markerClusterGroup is not a function at Map.svelte:25:48

Upvotes: 2

Views: 506

Answers (2)

Carlos Torrecillas
Carlos Torrecillas

Reputation: 5756

In my case, if that's of any use, I was also having trouble with the dynamic imports I had to do the following:

const L = await import('leaflet');
await import('leaflet.markercluster');

and then I had to use the window variable to create the market cluster group:

const groups = window.L.markerClusterGroup();

that way I got it working. Note I am using Angular but I am executing that piece of code only in the browser.

Package versions:

"leaflet": "^1.9.4",
"leaflet.markercluster": "^1.5.3",

"@types/leaflet": "1.9.8",
"@types/leaflet.markercluster": "^1.5.4",

Hope that helps too.

Upvotes: 1

CuriousCI
CuriousCI

Reputation: 150

Instead of just importing await import('leaflet.markercluster');, you should give it a name: const markercluster = await import('leaflet.markercluster');

and try to instantiate directly the MarkerClusterGroup class: const markerClusterGroup = new markercluster.MarkerClusterGroup();

I should check why it doesn't add the markerClusterGroup() function to leaflet, but this is a good temporary solution.

enter image description here

If you check the GitHub repo, the function is just a proxy for the constructor, you can just use it directly.

Upvotes: 2

Related Questions