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.

1 Like

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.

2 Likes

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.

@lewiseason how did you manage it with the turbolinks? because i’ve implemented this leaflet map with stimulus js but its throw me error regarding the map is already intialize due to turbolinks cashe stuff

You need to add a disconnect function to remove the map, as in Jefff’s implementation above. Otherwise, as far as Turbo is concerned, that first instance is still loaded.

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

For anyone still searching for this, I’m going through the process of implementing this exact thing in my app. I’m documenting everything along the way here AdventurePlane Dev Log 0 - StimulusJs and Leaflet

I’ll share the final source code once I’ve completed the implementation on the weekly newsletter, otherwise you can see all the snippets I’m finding and using in real time in that dev log :slight_smile: hope it helps someone!

For anyone interested. I finished V1 of my stimulus + leaflet implementation.

I’m going to remove some duplication and refactor some stuff. But here is the entire JS controller and HTLM from my production app.

AdventurePlane Dev Log 6- Stimulus + Leaflet v1

Demo of Stimulus with Leaflet and Open Layers. A Rails 7 demo.