Folium – Exporting GeoJSON with Defined Properties Using Draw Plugin

foliumleafletleaflet-drawpython

I used a nice plugin for python folium:

https://www.youtube.com/watch?v=rAicpbCUwco&ab_channel=SudoControl

but the problem is, that my saved geojson file has no properties.

enter image description here

I tried to inject JS to my folium code:

drawjs = """
map.on(L.Draw.Event.CREATED; function (e) {
var type = e.layerType,
layer = e.layer;
var title = prompt("Please provide the name", "default");
var value = prompt("Please provide the value", "undefined");
var id = x++
e.feature.setProperties({
'Id': id,
'Name': title,
'Value': value,
});
});
"""


draw = plugins.Draw(
  drawjs,
  export=True,
  filename='drawing.geojon',
  position='topleft'
)
map.add_child(draw)

Unfortunately, I have an error:

<module>
draw = plugins.Draw(
TypeError: __init__() got multiple values for argument 'export'

which means, that I've used the wrong argument for attaching the JS code to my plugin.

How can it be sorted out?

UPDATE:

After solving an issue here:

https://stackoverflow.com/questions/74536711/python-folium-problem-with-editing-draw-plugin

I am on the right track to sorting it out.
The piece of code where an error occurs looks like this:

 var {{ this.get_name() }} = new L.Control.Draw(
            options
        ).addTo( {{this._parent.get_name()}} );
        {{ this._parent.get_name() }}.on(L.Draw.Event.CREATED, 
    function(e) {
            let x = 1 // defining autoincrement ID
            var layer = e.layer,
                type = e.layerType;
            var title = prompt("Please provide the name", "default");
            var value = prompt("Please provide the value", 
          "undefinied");
            var id = x++
            var coords = JSON.stringify(layer.toGeoJSON());
            {%- if this.show_geometry_on_click %}
            layer.on('click', function() {
                alert(coords);
                console.log(coords);
                e.feature.setProperties({
                'Id': id,
                'Name': title,
                'Value': value,
                });
            });
            {%- endif %}
            drawnItems.addLayer(layer);
         });

where the JS console error states:

Uncaught TypeError: Cannot read properties of undefined (reading 'setProperties')

Best Answer

The JS script to be used in Python code:

$(document).ready(function(){           
    var x = 0;
    
    // {map} will be replaced to map object using Python
    {map}.on("draw:created", function(e){

        // get layer and feature    
        var layer = e.layer;
            feature = layer.feature = layer.feature || {}; 
        
        // user input
        var title = prompt("Please provide the name", "default");
        var value = prompt("Please provide the value", "undefined");
        var id = x++;

        feature.type = feature.type || "Feature";
        var props = feature.properties = feature.properties || {};

        // set properties
        props.Id = id;
        props.Title = title;
        props.Value = value;

        // add the drawn feature to the layer
        drawnItems.addLayer(layer);
      });    
    });

You need map.get_root().html to get html, and add_child method to add JavaScript to the page.

import folium
from folium.plugins import Draw

m = folium.Map()

Draw(export=True,
     filename='drawing.geojson',
     position = 'topleft').add_to(m)

mapObjectInHTML = m.get_name()

m.get_root().html.add_child(folium.Element("""
<script type="text/javascript">
  $(document).ready(function(){           
    var x = 0;
    
    {map}.on("draw:created", function(e){    
        var layer = e.layer;
            feature = layer.feature = layer.feature || {}; 
            
        var title = prompt("Please provide the name", "default");
        var value = prompt("Please provide the value", "undefined");
        var id = x++;

        feature.type = feature.type || "Feature";
        var props = feature.properties = feature.properties || {};
        props.Id = id;
        props.Title = title;
        props.Value = value;
        drawnItems.addLayer(layer);
      });    
    });    
</script>
""".replace('{map}', mapObjectInHTML)))

m

enter image description here

drawing.geojson for the image above:

{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "properties": { "Id": 0, "Title": "default", "Value": "undefined" },
      "geometry": {
        "type": "Polygon",
        "coordinates": [
          [
            [-48.515625, 11.178402],
            [30.9375, 48.922499],
            [58.359375, -13.239945],
            [-48.515625, 11.178402]
          ]
        ]
      }
    },
    {
      "type": "Feature",
      "properties": { "Id": 1, "Title": "default", "Value": "undefined" },
      "geometry": {
        "type": "Polygon",
        "coordinates": [
          [
            [7.03125, 55.776573],
            [-56.953125, 26.431228],
            [-87.1875, 64.168107],
            [7.03125, 55.776573]
          ]
        ]
      }
    }
  ]
}