A more complete, working version of this blog post for creating, editing, and deleting points from or to a CARTO points-geometry table. Some modifications would be needed on the front-end side to have this work for a polygons or lines table. CARTO has a limitation of only one type of geometry per table, so you would either want to limit users to Leaflet.draw'ing one geometry type, or otherwise creating new/separate functions and loading from separate tables for different types.
Built with blockbuilder.org
xxxxxxxxxx
<html>
<head>
<title>Leaflet Draw</title>
<link rel="stylesheet" href="https://libs.cartocdn.com/cartodb.js/v3/3.15/themes/css/cartodb.css" />
<script src="https://libs.cartocdn.com/cartodb.js/v3/3.15/cartodb.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet.draw/0.4.3/leaflet.draw.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet.draw/0.4.3/leaflet.draw.js"></script>
</head>
<body>
<div id="map" style="position: absolute; top: 0; left: 0; width: 80%; height: 80%;"></div>
<script>
//initialize the map with Leaflet
var map = new L.Map('map', {center: new L.LatLng(40.7, -74), zoom: 11});
//add a carto basemap tile layer
var carto = L.tileLayer('https://cartodb-basemaps-{s}.global.ssl.fastly.net/light_all/{z}/{x}/{y}@2x.png', {
maxZoom: 18,
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>, © <a href="https://carto.com/attributions">CARTO</a>'
}).addTo(map);
//prep the draw FeatureGroup and add Leaflet.draw controls to map
var drawnItems = new L.FeatureGroup();
var drawControl = new L.Control.Draw({
position: 'topright',
draw: {
polyline: false,
polygon: false,
circle: false,
rectangle: false,
marker: true
},
edit: {
featureGroup: drawnItems,
remove: true
}
});
map.addControl(drawControl);
//create cartodb.SQL object to grab geojson of table
//see here https://carto.com/blog/the-versatility-of-retreiving-and-rendering-geospatial
var sql = new cartodb.SQL({ user: 'athompson', format:'GeoJSON'});
sql.execute("SELECT * FROM areas_of_interest_newyork_nycsanitation")
.done(function(data) {
//add geojson features to the drawnItems FeatureGroup
//console.log(data);//optional/debugging
geojsonLayer = L.geoJson(data, {
onEachFeature: function (feature, layer) {
layer.cartodb_id=feature.properties.cartodb_id;
drawnItems.addLayer(layer);
}
});
//add the drawnItems FeatureGroup, populated with geojson from carto table, to the map
map.addLayer(drawnItems);
})
.error(function(errors) {
// errors contains a list of errors
console.log("errors:" + errors);
});
function persistOnCartoDB(action, layers) {
/*
this function interacts with the Security Definer
function previously defined in our CARTO account.
Gets an action (update, insert, or delete) and a list
of GeoJSON objects (the geometry objects only, to work
with ST_GeomFromGeojson()) with which to change the table.
see https://gis.stackexchange.com/questions/169219/invalid-geojson-when-inserting-data-to-a-cartodb-postgis-table-from-leaflet
*/
var cartodb_ids = [];
var geojsons = [];
//console.log(action + " persistOnCartoDB");
switch (action) {
case "UPDATE":
//console.log(layers.getLayers().length);
if (layers.getLayers().length < 1) return;
layers.eachLayer(function(layer) {
cartodb_ids.push(layer.cartodb_id);
geojsons.push("'" + JSON.stringify(layer.toGeoJSON().geometry) + "'");
});
break;
case "INSERT":
cartodb_ids.push(-1);
//console.log("here is the geojsons");
//console.log(geojsons);
//console.log("'" + JSON.stringify(layers.toGeoJSON().geometry) + "'");
geojsons.push("'" + JSON.stringify(layers.toGeoJSON().geometry) + "'");
break;
case "DELETE":
layers.eachLayer(function(layer) {
cartodb_ids.push(layer.cartodb_id);
geojsons.push("''");
});
break;
}
//constructs the SQL statement
var sql = "SELECT nyc_sanitation_example_upsert_areas_of_interest_newyork_nycsanitation(ARRAY[";
sql += cartodb_ids.join(",");
sql += "],ARRAY[";
sql += geojsons.join(",");
sql += "]);";
console.log("persisting... " + sql);//optional/debugging
//POST the SQL up to CARTO
$.ajax({
type: 'POST',
url: 'https://athompson.carto.com/api/v2/sql',
crossDomain: true,
data: {
"q": sql
},
dataType: 'json',
success: function(responseData, textStatus, jqXHR) {
console.log("Data saved");
if (action == "INSERT")
layers.cartodb_id = responseData.rows[0].cartodb_id;
},
error: function(responseData, textStatus, errorThrown) {
console.log("Problem saving the data " + responseData);
}
});
}
//bind drawing events to fire the persistOnCartoDB() function
map.on('draw:created', function (e) {
//console.log("draw:created fired");
var layers = e.layer;//was e.layers not layer
drawnItems.addLayer(layers);
//console.log(e);
persistOnCartoDB("INSERT", layers);
//console.log("draw:created:insert persistOnCartoDB fired");
});
map.on('draw:edited', function (e) {
//console.log("draw:edited fired");
var layers = e.layers;
persistOnCartoDB("UPDATE", layers);
//console.log("draw:edited:update persistOnCartoDB fired");
});
map.on('draw:deleted', function (e) {
//console.log("draw:deleted fired");
var layers = e.layers;
persistOnCartoDB("DELETE", layers);
//console.log("draw:deleted:delete persistOnCartoDB fired");
});
</script>
</body>
</html>
Modified http://libs.cartocdn.com/cartodb.js/v3/3.15/cartodb.js to a secure url
https://libs.cartocdn.com/cartodb.js/v3/3.15/cartodb.js
https://cdnjs.cloudflare.com/ajax/libs/leaflet.draw/0.4.3/leaflet.draw.js