Gregory Shein
Gregory Shein

Reputation: 41

Edit a single polygon in react leaflet

So I'm using https://github.com/alex3165/react-leaflet-draw

I want to make some particular polygon editable when you click a pencil button outside of the map. Right now there is a button "edit layers" but it naturally makes all of them editable, can I do it on polygon by polygon basis?

So I would want to do smth like this: map to edit polygons

I opened an issue https://github.com/alex3165/react-leaflet-draw/issues/79 but not much success there

The thing is through refs I can get a giant circular object: this is what I get when I console.log .drawControl._toolbars.edit._modes.edit.handler.options.featureGroup._layers[57]

Upvotes: 4

Views: 5097

Answers (2)

manoj garu
manoj garu

Reputation: 163

const [mapLayers, setMapLayers] = useState([]);

const _onEdited = (e) => {
    e.layers.eachLayer(a => {
      const { _leaflet_id } = a;
      setMapLayers((layers) => [
        ...layers,
        { id: _leaflet_id, latlngs: a.getLatLngs()[0] },
      ]);
    });
  }

Upvotes: 0

Vadim Gremyachev
Vadim Gremyachev

Reputation: 59368

One option to consider is to create editable layer per every shape(feature), in a way that instead of creating EditControl control for a collection of features:

<FeatureGroup>
    <EditControl
      position="topright"
    />
</FeatureGroup>

create EditControl instance per every feature from GeoJSON:

<FeatureGroup>
    <EditControl
      position="topright"
    />
</FeatureGroup>
...
<FeatureGroup>
    <EditControl
      position="topright"
    />
</FeatureGroup>

The following example demonstrates this approach where:

  • only a single shape could be edited at a time
  • switching from one editable layer to another occurs on layer click

Example:

function EditableGroup(props) {
  const [selectedLayerIndex, setSelectedLayerIndex] = useState(0);

  function handleLayerClick(e) {
    setSelectedLayerIndex(e.target.feature.properties.editLayerId);
  }

  let dataLayer = new L.GeoJSON(props.data);
  let layers = [];
  let i = 0;
  dataLayer.eachLayer((layer) => {
    layer.feature.properties.editLayerId = i;
    layers.push(layer);
    i++;
  });

  return (
    <div>
      {layers.map((layer, i) => {
        return (
          <EditableLayer
            key={i}
            layer={layer}
            showDrawControl={i === selectedLayerIndex}
            onLayerClicked={handleLayerClick}
          />
        );
      })}
    </div>
  );
}

where

function EditableLayer(props) {
  const leaflet = useLeaflet();
  const editLayerRef = React.useRef();
  let drawControlRef = React.useRef();
  let {map} = leaflet;

  useEffect(() => {
    
    if (!props.showDrawControl) {
      map.removeControl(drawControlRef.current);
    } else {
      map.addControl(drawControlRef.current);
    }

    editLayerRef.current.leafletElement.clearLayers();

    editLayerRef.current.leafletElement.addLayer(props.layer);
    props.layer.on("click", function (e) {
      props.onLayerClicked(e, drawControlRef.current);
    });
  }, [props, map]);

  function onMounted(ctl) {
    drawControlRef.current = ctl;
  }

  return (
    <div>
      <FeatureGroup ref={editLayerRef}>
        <EditControl
          position="topright"
          onMounted={onMounted}
          {...props}
        />
      </FeatureGroup>
    </div>
  );
}

Here is a demo for the reference

Upvotes: 3

Related Questions