Search code examples
javascriptvue.jsvuejs2leafletleaflet.markercluster

ClassName undefined for some child in iconCreateFunction


I'm working in a Vue2 web application using Leaflet and marker-cluster I have some issue with the iconCreateFunction option Here is a part of my tempate :

 <v-marker-cluster :options="{ iconCreateFunction: iconCreateClsPrg}">
          <l-marker ....> 
                <l-icon :class-name="programme.display ? 'custom-marker notDisplay' : 'custom-marker display'">

And here is a part of the iconCreateClsPrg method :

iconCreateClsPrg (marker_cluster) {
        const childs = marker_cluster.getAllChildMarkers();
         childs.forEach(child => {
            const cssCluster = child.options.icon.options.className;
            if (cssCluster && cssCluster.includes(this.css_marker_selected_simple)) {
                nbSelected++;
            }
          }
             ...
}

My problem is that sometimes my cssCluster const is undefined for no reason. It's not a regular behavior and it happens only at some zoom levels (which are not always the same). If someone has an idea, it would be a big help !

I tryied to refresh the map, to wait until undefined (but had some issu with async method), restart the method from scratch, use for instead of forEach, ... but nothing worked


Solution

  • I finally found a way to wait until the icon is fully loaded using promises :

    iconCreateClsPrg (marker_cluster) {
                let nbSelected = 0;
                try {
                    const childs = marker_cluster.getAllChildMarkers();
                    const promises = [];
                    childs.forEach(child => {
                        // create promise to wait for all child
                        const promise = new Promise(resolve => {
                            // wait for 0ms to let the browser render the page asynchonously
                            setTimeout(() => {
                                const cssCluster = child.options.icon.options.className;
                                if (cssCluster && cssCluster.includes(this.css_marker_selected_simple)) {
                                    nbSelected++;
                                }
                                resolve();
                            }, 0);
                        });
                        promises.push(promise);
                    });
                    // wait for all child to be processed before continue
                    Promise.all(promises).then(() => {
                        // do the rest of my things
                        const divIcon = new L.DivIcon({
                            html: htmlContent,
                            className: css_cluster,
                            iconSize: [30 + childCount, 30 + childCount],
                        });
    
                        // Ensure the map updates the cluster icon after the promise has resolved
                        marker_cluster.setIcon(divIcon);
                    });
                } catch (e) {
                    // deal with the error
                }
                // Return a blank icon to start with
                return new L.DivIcon({
                });
            }