geoman-io / leaflet-geoman

🍂🗺️ The most powerful leaflet plugin for drawing and editing geometry layers
https://geoman.io
MIT License
2.21k stars 433 forks source link

Programmatically remove/add controls in event handler #796

Closed tobilg closed 3 years ago

tobilg commented 3 years ago

I'm currently trying to use leaflet-geoman together with leaftlet-react via the MapConsumer component:

<MapContainer
  center={[50,0]}
  zoom={5}
  scrollWheelZoom={true}
  style={{ height: '100vh', width: '100wh' }}
>
  <TileLayer
      attribution='&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
      url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
    />
  <MapConsumer>
    {(map) => {

      map.pm.addControls({  
        position: 'topleft',  
        drawCircle: true,
        drawRectangle: true,
        drawPolygon: true,
        drawCircleMarker: false,
        drawMarker: false,
        drawPolyline: false,
      });

      map.on("pm:create", (e) => {
        this.handleLayer(map, e.layer, "CREATE", e.shape);
        e.layer.on("pm:edit", f => {
          this.handleLayer(map, f.target, "UPDATE", f.shape)
        })
      });

      map.on("pm:remove", (e) => {
        this.handleLayer(map, e.layer, "DELETE", e.shape);
      });

      return null
    }}
  </MapConsumer>
</MapContainer>

The handleLayer() function looks like this:

handleLayer = (map, layer, action, shape) => {
  switch (action) {
    case "CREATE":
      console.log(`CREATE ${shape}`);
      // Remove controls
      map.pm.removeControls();
     // Only use edit controls
      map.pm.addControls({  
        position: 'topleft',  
        drawCircle: false,
        drawRectangle: false,
        drawPolygon: false,
        drawCircleMarker: false,
        drawMarker: false,
        drawPolyline: false,
      });
      // Create state
      this.setState({ geoJSON: this.getGeoJSON(layer, shape) })
      break;
    case "UPDATE":
      console.log(`UPDATE ${shape}`);
      // Update state
      this.setState({ geoJSON: this.getGeoJSON(layer, shape) })
      break;
    case "DELETE":
      console.log(`DELETE ${shape}`);
      // Remove edit-only controls
      map.pm.removeControls();
      // Add back full controls once the existing layer has been deleted
      map.pm.addControls({  
        position: 'topleft',  
        drawCircle: true,
        drawRectangle: true,
        drawPolygon: true,
        drawCircleMarker: false,
        drawMarker: false,
        drawPolyline: false,
      });
      // Remove from state
      this.setState({ geoJSON: null })
      break;
    default:
      break;
  }
  return null;
}

My use case is that I only want to allow to add one shape to the map, and once a shape has been added there should only be the edit controls visible. The above code executed without errors, but doesn't remove/re-add the controls unfortunately. So far I couldn't find a solution. Any ideas/hints?

Falke-Design commented 3 years ago

Please create a demo. You can use this as template: https://codesandbox.io/s/angry-babbage-cns52?file=/src/App.tsx