Search code examples
leafletmapboxgeojson

Editing/Removing GeoJSON layers from a featureGroup in Mapbox using Leaflet


I'm using Mapbox with Leaflet for drawing, editing and removing polygons etc. Every time I create a new polygon, I convert them to a GeoJSON layer and then add it to the featureGroup that I created, because I want to associate each layer with an ID property that I can use later. This is what I have:

var featureGroup = L.featureGroup().addTo(map);

var drawControl = new L.Control.Draw({
    edit: {
        featureGroup: featureGroup
    },
    draw: {
        polygon: {
            allowIntersection: false
        },
        polyline: false,
        rectangle: false,
        circle: false,
        marker: false
    }
}).addTo(map);

map.on('draw:created', addPolygon);
map.on('draw:edited', editPolygon);
map.on('draw:deleted', deletePolygon);

function deletePolygon(e) {
    featureGroup.removeLayer(e.layer);
}

function editPolygon(e) {
    featureGroup.eachLayer(function (layer) {
        layer.eachLayer(function (layer) {
            addPolygon({ layer: layer });
        });
    });
}

function addPolygon(e) {
    var geojsonstring = e.layer.toGeoJSON();
    var geojson = L.geoJson(geojsonstring);
    featureGroup.addLayer(geojson);
}

When I do this, creating polygons is not a problem. But when I try to edit or delete polygons, it doesn't work properly.

When I try to edit a polygon, it tells me "TypeError: i.Editing is undefined". It doesn't allow me to cancel editing as well.

When I try to delete a polygon, it is not displayed in the map anymore, but it is still not removed from the featureGroup.

What am I doing wrong here?

Edit: The way I'm currently doing this is the same way that ghybs has suggested. But the problem is, once all the edits are done, the polygons are saved to a database (I convert it to a WKT string to save in SQLServer). And when the page is loaded the next time, the polygons are loaded back from the database, and the user can edit or delete them and save it back to the database.

As it is right now, when the user makes the edit and saves them again, it only creates duplicate polygons. and I don't know of any way to connect the edited polygons to the ones from the database.

So I thought if I could convert them to GeoJSON and assign an ID property to each layer (something like ID=0 if it is a new layer, and the corresponding polygonID from the database if it is loaded from the database). So that when they are saved again, I can check this ID and based on that, I can either update the available polygon, or create a new polygon in the database.

Is there a better way of doing this?


Solution

  • Not sure exactly why in addPolygon you go through a GeoJSON object that you convert back into a Leaflet layer group through L.geoJson?

    You could have directly added the created layer, as in Leaflet.draw "draw:created" example:

    function addPolygon(e) {
      var layer = e.layer;
      var feature = layer.feature = layer.feature || {}; // Initialize layer.feature
      // use the feature.id: http://geojson.org/geojson-spec.html#feature-objects
      feature.id = 0; // you can change it with your DB id once created.
      featureGroup.addLayer(layer);
    
      // record into DB, assuming it returns a Promise / Deferred.
      recordToDb(layer.toGeoJSON()).done(function (result) {
        feature.id = result.id; // Update the layer id.
      });
    }
    

    As for the reason for you error, it is due to the fact that you add a (GeoJSON) Layer Group to your featureGroup, which Leaflet.draw plugin does not know how to handle. You must add only "non group" layers.

    See also: https://gis.stackexchange.com/questions/203540/how-to-edit-an-existing-layer-using-leaflet