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.

  • Polymer npm app running in express static dir causes errors when importing files

    I have a node application serving API backed and application frontend. Backed uses Express and static route to serve front end from "views" directory. The front is a static app using Polymer 3. I am unable to preview the UI when serving it from my backed because of modules resolution. So when I am developing the app I have to use polymer serve --npm command. And so for it worked. However now I am working on a part when the API returns data for logged in user. Because both applications (backend and frontend) are in different origins (different ports) the UI won't let me use the API even if I am logged in in backend.

    So the question is if there's a way to use polymer's polyserve module in a combination with express router so I can work with both applications on the same port?