Stimulus Discourse

Leafletjs with Stimulusjs on Rails 6

Hi,

Anybody integrated Leafletjs for maps with stimulusjs ?

Is it good to have it with stimulusjs ?

Please share the code(gitlab/github) repo link if it is available.

Please throw some light on it.

Thanks.

It is a bit complicated to make it work with webpack. The easiest way for me was to include the css in the html not webpack due to some broken icons URLs.

The JavaScript part is provided by webpack, as it is quite heavy and used only on one page I lazy load it.

I use this html

<% content_for(:css_head) do %>
<% end %>
<%= tag.div(id: "mapid", class: "z-10 mb-4 h-64 bg-gray-200",
                data: {controller: "map",
                       target: "map.placeholder",
                       map_latitude: advert.latitude,
                       map_longitude: advert.longitude}
               ) %>

With this stimulus controller

import { Controller } from "stimulus"

export default class extends Controller {
  static targets = [ "placeholder" ]

  connect(){
    import("leaflet").then( L => {
      this.map = L.map(this.placeholderTarget).setView(this._coordinates(), 10);

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

  disconnect(){
    this.map.remove()
  }

  _coordinates(){
    return [this.data.get("latitude"), this.data.get("longitude")]
  }
}

I hope this helps. Default zoom value should be a data attribute too.

Have fun.

1 Like

He @Jefff

Could you please share the working copy of the repository.

Thanks.

Hi @Kiran_Patil,

I have an app which uses Stimulus and Leaflet. It’s not an open source project, so I can’t share the repository unfortunately, but everything works as you would expect. Here’s the basics of how I’m set up:

<div class="map-container" data-target="map.container"></div> 

Then my controller looks a bit like this:

// map_controller.js
import { Controller } from "stimulus"
import "leaflet/dist/leaflet.css"
import L from "leaflet"

export default class extends Controller {
  static targets = [
    "container",
  ]

  connect() {
    this.map = L.map(this.containerTarget, {
      zoomDelta: 0.5,
      zoomSnap: 0.5,
    })
    
    // this.map.setView() etc... as normal.

    // Load layers and setup event handlers, for example:
    fetch("http://example.com/data.geojson")
      .then(response => response.json())
      .then(data => {
        L.geoJSON(data, {
          onEachFeature: (feature, layer) => {
            layer.on('click', () => this.onClick(layer))
          }
        })
      })

  }

  onClick(layer) {
    console.log(layer)
  }
}

What you do next will depend on how you’re planning to do with the map, but that should be enough to get you started. Jefff’s comment has some good hints, and this plugin might be useful if you run into the same webpack issues.