Can't load leaflet map onto polymer 3 element

So I'm trying to get my leaflet map to load onto my polymer 3 element, but I have an issue because I need the html div tag for the map to load BEFORE my leaflet javascript, or else it throws an error saying there's no container for it. I can't figure out a way to do this because I'm importing my javascript in so it's always going to load first. I need polymer to somehow let me load the html tag before rendering the javascript. Here is the code for the polymer element:

import { PolymerElement, html } from '@polymer/polymer/polymer-element.js';
import './shared-styles.js';
import './leaflet/leaflet.js';



class MyView1 extends PolymerElement {
  static get template() {
    return html`
      <style include="shared-styles">
        :host {
          display: block;

          padding: 10px;
        }
      </style>

      <div class="card">
        <div class="circle">1</div>
        <h1>View One</h1>
        <div id="map" style="width: 900px; height: 500px"></div>

      </div>
    `;
  }
}

window.customElements.define('my-view1', MyView1);

2 answers

  • answered 2018-10-20 08:54 Pascal L.

    import can also be used asyc. Move your import to ready lifecycle callback this way your dom is definitly ready.

    import { PolymerElement, html } from '@polymer/polymer/polymer-element.js';
    import './shared-styles.js';
    
    class MyView1 extends PolymerElement {
        static get template() {
            return html`
                <style include="shared-styles">
                    :host {
                        display: block;
                        padding: 10px;
                    }
                </style>
    
                <div class="card">
                    <div class="circle">1</div>
                    <h1>View One</h1>
                    <div id="map" style="width: 900px; height: 500px"></div>
                </div>
        `;
      }
    
      ready(){
          super.ready();
          import('./leaflet/leaflet.js').then((leafletModule) => {
              //leaflet is now imported
          });
      }
    }
    
    window.customElements.define('my-view1', MyView1);
    

  • answered 2018-10-20 13:36 User 28

    I'm not sure what's inside your leaflet.js. If it's only a bundle from leaflet the problem is not about loading order because leaflet didn't execute anything until you call their functions. But if it contains your initialize code. I would suggest you to create an init function and call it from outside.

    If you initialize the map like:

    let myMap = L.map('mapId')
    

    You will got an Uncaught Error: Map container not found. because of if you pass string, leaflet will use document.getElementById function to find the container element which will cannot be found because of Shadow DOM. Fortunately leaflet allow you to pass the HTMLElement so you can do like:

    let myMap = L.map(this.$.map)
    

    The final code will be like:

    import { PolymerElement, html } from '@polymer/polymer/polymer-element.js'
    import { style, map, tileLayer } from './leaflet.js'
    
    const styleElement = document.createElement('dom-module')
    
    styleElement.innerHTML =`
      <template>
        <style>
          ${style}
        </style>
      </template>
    `
    
    styleElement.register('shared-styles')
    
    class MyView1 extends PolymerElement {
      static get template() {
        return html`
          <style include='shared-styles'></style>
          <div class='card'>
            <div id='map' style='width: 900px; height: 500px'></div>
          </div>
        `
      }
    
      ready () {
        super.ready()
    
        let myMap = map(this.$.map, {
          center: [51.505, -0.09],
          zoom: 13
        })
    
        tileLayer('https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token=pk.eyJ1IjoibWFwYm94IiwiYSI6ImNpejY4NXVycTA2emYycXBndHRqcmZ3N3gifQ.rJcFIG214AriISLbB6B5aw', {
          id: 'mapbox.streets'
        }).addTo(myMap)
      }
    }
    
    window.customElements.define('my-view1', MyView1)
    

    I use rollup to bundle leaflet.js, see config here.

    And working example here.