Search code examples
javascriptpluginsleafletes6-modulesreact-leaflet

Using Leaflet.Path.Drag plugin with React Leaflet


Leaflet.Path.Drag is a plugin to the Leaflet library. It works by patching the global L instance that Leaflet adds to the window. This mechanism works fine when Leaflet and the plugin are incorporated in an app via script tags. But in a modern TS/React app that uses ES6 modules, simply installing the two packages and then importing them doesn't achieve the needed plugin integration. To get the plugin to work I've tried the following in my Reach Leaflet app, as recommended here:

// Import Leaflet into L 
import * as L from 'leaflet';

// Import the plugin library so it will modify L
import 'leaflet-path-drag';

const createDraggablePolygon = () => {
  const geometry = {
    type: "Polygon",
    coordinates: [[[0, 0], [0, 1], [1, 1], [1, 0], [0, 0]]]
  }
  const geoJson = L.geoJSON(geometry, {});
  // plugin should add 'dragging' property to the GeoJSON object
  assert("dragging" in geoJson);
}

This doesn't work either (the assertion fails). Suggestions?

One clarification: I am not trying to build a plugin for React Leaflet (at least if I can avoid it). In my case it's fine if the behaviors exposed by the plugin are only available through Leaflet elements and not through the React Leaflet library.


Solution

  • I found the problem. The solution above actually patches the Leaflet library correctly. The reason the geoJSON layer didn't have the dragging property was that it extends LayerGroup so you need to include an onEachFeature function in the options. The layers that Leaflet passes into that function are the ones that have been patched with the dragging property. So I needed something like this:

    // Import Leaflet into L 
    import * as L from 'leaflet';
    
    // Import the plugin library so it will modify L
    import 'leaflet-path-drag';
    
    const initDraggableLayer = (feature, layer) => {
      // plugin adds 'dragging' property to this layer
      assert("draggable" in layer);
    } 
    
    const createDraggablePolygon = () => {
      const geometry = {
        type: "Polygon",
        coordinates: [[[0, 0], [0, 1], [1, 1], [1, 0], [0, 0]]]
      }
      const geoJson = L.geoJSON(geometry, {
        onEachFeature: initDraggableLayer
      });
    }