2

The JS based custom element below appear to work but can not find the mapid div that I add to the shadow DOM root. Is there a way in Leaflet or custom elements to allow stock Leaflet (version 1.4 which is the latest as of this writing) to find and use a shadow DOM-based mapid div?

error:

Uncaught Error: Map container not found.
    at NewClass._initContainer (Map.js:1102)
    at NewClass.initialize (Map.js:136)
    at new NewClass (Class.js:22)
    at Module.createMap (Map.js:1717)
    at new GDMap (gd-map.js:16)
    at gd-map.js:30
    at gd-map.js:31

I'm going on the approach that this simply is a case where Leaflet is looking for the mapid div in the dom root and can't find it in the shadow dom.

Javascript

import * as L from './leaflet/leaflet-src.esm.js';

(function () {
    class GDMap extends HTMLElement {
        constructor() {
            super();

            this.attachShadow({ mode: 'open' });
            this.shadowRoot.innerHTML = `<div style="height:180px" id="mapid"></div>`;

           var map = L.map('mapid').setView([51.505, -0.09], 13);

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

            }).addTo(map);


            L.marker([51.5, -0.09]).addTo(map)
                .bindPopup('A pretty CSS3 popup.<br> Easily customizable.')
                .openPopup();

        }
    }
    window.customElements.define('geodex-map', GDMap);
})();

edited post to align div id as pointed out.. still same issue though.

IvanSanchez
  • 18,272
  • 3
  • 30
  • 45
Douglas Fils
  • 311
  • 4
  • 14
  • Pal, you're defining`
    ` and then calling `L.map("map")` - please double-check this is not just a simple typo.
    – IvanSanchez Apr 02 '19 at 09:11
  • @IvanSanchez thanks.. I'll update the post but it's the exact same issue. You are correct I had them miss-matched but it didn't resolve it. I can inspect the dom tree and clearly see my div id="mapid" being there and rendering with the proper height. Still Leaflet will not see it. – Douglas Fils Apr 02 '19 at 09:25
  • OK.. I think I resolved it.. I had to pass the div as an element and not let Leaflet look for it by ID. (then add in the style sheet) – Douglas Fils Apr 02 '19 at 10:11
  • It seems that you found the answer by yourself about 30 seconds before I could hit "send" on my answer :-) – IvanSanchez Apr 02 '19 at 10:16

2 Answers2

2

Trying to instantiate a Leaflet map before its container is in the DOM is a known problem, with a known solution:

The <div id="leafletmap"> must be added to the dom before calling L.map('leafletmap').

But you already know this, because you're making a very good and specific question:

Is there a way in [Leaflet 1.4] to find and use a shadow DOM-based mapid div?

The answer is "no, but".

If you read carefully the Leaflet API reference, you'll notice that a L.Map can be instantiated in two ways: either by providing the id of the HTMLElement that will be the map's container, or by providing the HTMLElement instance of the container.

In other words, something along the lines of:

var mapdiv = document.createElement('div');
shadow.appendChild(mapdiv);
var map = L.map(mapdiv)
IvanSanchez
  • 18,272
  • 3
  • 30
  • 45
1

I think the following resolves it now.

Needed to pass the map div as an element not provide an id string for Leaflet to find. The also pass along the CSS.

import * as L from './leaflet/leaflet-src.esm.js';

(function () {
    class GDMap extends HTMLElement {
        constructor() {
            super();

            let shadow = this.attachShadow({mode: 'open'});
            var mapdiv = document.createElement('div');
            mapdiv.setAttribute('id', 'mapid');
            // mapdiv.setAttribute('style', 'height:180px');
            mapdiv.style.height = "180px";
            mapdiv.innerHTML = ' <link rel="stylesheet" href="https://unpkg.com/leaflet@1.4.0/dist/leaflet.css" integrity="sha512-puBpdR0798OZvTTbP4A8Ix/l+A4dHDD0DGqYW6RQ+9jxkRFclaxxQb/SJAWZfWAkuyeQUytO7+7N4QKrDh+drA=="crossorigin=""/>';
            shadow.appendChild(mapdiv);

            var map = L.map(mapdiv).setView([51.505, -0.09], 13);

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

            }).addTo(map);

            L.marker([51.5, -0.09]).addTo(map)
                .bindPopup('A pretty CSS3 popup.<br> Easily customizable.')
                .openPopup();

        }
    }
    window.customElements.define('geodex-map', GDMap);
})();

Douglas Fils
  • 311
  • 4
  • 14