Esri Leaflet

Editing feature layers

This sample uses the Leaflet Editable plugin to help users manipulate the geometry of features from a hosted feature service and pass the edits back to the server.

<html>
<head>
  <meta charset="utf-8" />
  <title>Editing feature layers</title>
  <meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" />

  <!-- Load Leaflet from CDN -->
  <link rel="stylesheet" href="https://unpkg.com/leaflet@1.5.1/dist/leaflet.css"
  integrity="sha512-xwE/Az9zrjBIphAcBb3F6JVqxf46+CDLwfLMHloNu6KEQCAWi6HcDUbeOfBIptF7tcCzusKFjFw2yuvEpDL9wQ=="
  crossorigin=""/>
  <script src="https://unpkg.com/leaflet@1.5.1/dist/leaflet.js"
  integrity="sha512-GffPMF3RvMeYyc1LWMHtK8EbPv0iNZ8/oTtHPx9/cc2ILxQ+u905qIwdpULaqDkyBKgOaB57QTMg7ztg8Jm2Og=="
  crossorigin=""></script>


  <!-- Load Esri Leaflet from CDN -->
  <script src="https://unpkg.com/esri-leaflet@2.3.0/dist/esri-leaflet.js"
  integrity="sha512-1tScwpjXwwnm6tTva0l0/ZgM3rYNbdyMj5q6RSQMbNX6EUMhYDE3pMRGZaT41zHEvLoWEK7qFEJmZDOoDMU7/Q=="
  crossorigin=""></script>


  <style>
    body { margin:0; padding:0; }
    #map { position: absolute; top:0; bottom:0; right:0; left:0; }
  </style>
</head>
<body>

<script src="https://unpkg.com/leaflet.path.drag@0.0.5"></script>
<script src="https://unpkg.com/leaflet-editable@1.2.0/src/Leaflet.Editable.js"></script>

<div id='map'></div>

<script type="text/javascript">
    // make sure double clicking the map *only* triggers the editing workflow
    var map = L.map('map', {
      editable: true,
      doubleClickZoom: false
    }).setView([37.345, -110.875], 5);

    L.esri.basemapLayer('Topographic').addTo(map);

    // create a feature layer and add it to the map
    var wildfireDistricts = L.esri.featureLayer({
      url: 'https://sampleserver6.arcgisonline.com/arcgis/rest/services/Wildfire/FeatureServer/2'
    }).addTo(map);

    // create a generic control to invoke editing
    L.EditControl = L.Control.extend({
      options: {
        position: 'topleft',
        callback: null,
        kind: '',
        html: ''
      },
      // when the control is added to the map, wire up its DOM dynamically and add a click listener
      onAdd: function (map) {
        var container = L.DomUtil.create('div', 'leaflet-control leaflet-bar');
        var link = L.DomUtil.create('a', '', container);
        link.href = '#';
        link.title = 'Create a new ' + this.options.kind;
        link.innerHTML = this.options.html;
        L.DomEvent
          .on(link, 'click', L.DomEvent.stop)
          .on(link, 'click', function () {
            window.LAYER = this.options.callback.call(map.editTools);
          }, this);
        return container;
      }
    });

    // extend the control to draw polygons
    L.NewPolygonControl = L.EditControl.extend({
      options: {
        position: 'topleft',
        callback: map.editTools.startPolygon,
        kind: 'polygon',
        html: '▰'
      }
    });

    // extend the control to draw rectangles
    L.NewRectangleControl = L.EditControl.extend({
      options: {
        position: 'topleft',
        callback: map.editTools.startRectangle,
        kind: 'rectangle',
        html: '⬛'
      }
    });

    // add the two new controls to the map
    map.addControl(new L.NewPolygonControl());
    map.addControl(new L.NewRectangleControl());

    // when users CMD/CTRL click an editable feature, remove it from the map and delete it from the service
    wildfireDistricts.on('click', function (e) {
      if ((e.originalEvent.ctrlKey || e.originalEvent.metaKey) && e.layer.editEnabled()) {
        e.layer.editor.deleteShapeAt(e.latlng);
        // delete expects an id, not the whole geojson object
        wildfireDistricts.deleteFeature(e.layer.feature.id);
      }
    });

    // when users double click a graphic toggle its editable status
    // when deselecting, pass the geometry update to the service
    wildfireDistricts.on('dblclick', function (e) {
      e.layer.toggleEdit();
      if (!e.layer.editEnabled()) {
        wildfireDistricts.updateFeature(e.layer.toGeoJSON());
      }
    });

    // when a new feature is drawn using one of the custom controls, pass the edit to the service
    map.on('editable:drawing:commit', function (e) {
      wildfireDistricts.addFeature(e.layer.toGeoJSON());
      e.layer.toggleEdit();
    });
</script>

</body>
</html>