0

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 Answers2

0

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);
Pascal L.
  • 1,261
  • 9
  • 21
0

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.

User 28
  • 4,863
  • 1
  • 20
  • 35
  • so it's not the bundle from leaflet, it's my own leaflet file where i'm declaring my map and such. When i use "let myMap = map(this.$.map, ....." I get an error saying "$ is undefined", probably since my leaflet file isn't a polymer file. – Nima Sarrafzadeh Oct 23 '18 at 16:33
  • Then you shouldn't use `this.$.map` inside your leftlet file, instead you should wrap your code in a function like `init` and pass the map element when you call like `init(this.$.map)` in ready function. – User 28 Oct 24 '18 at 04:41