Esri Leaflet

Editing feature layers

This sample uses the Leaflet Editable plugin (coupled with the Leaflet.Path.Drag 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.1/dist/esri-leaflet.js"
  integrity="sha512-Np+ry4Dro5siJ1HZ0hTwn2jsmu/hMNrYw1EIK9EjsEVbDge4AaQhjeTGRg2ispHg7ZgDMVrSDjNrzH/kAO9Law=="
  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.6/src/Path.Drag.js"></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 active 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()) {
        // 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
    // but when deselecting via double click, 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 featureLayer service
    map.on('editable:drawing:commit', function (e) {
      wildfireDistricts.addFeature(e.layer.toGeoJSON(), function (error, response) {
        if (error || !response.success) {
          console.log(error, response);
        }

        // now that the L.esri.featureLayer instance will manage this new feature,
        // remove any temporary features from the map that were created by the Editable plugin
        map.editTools.featuresLayer.clearLayers();
      });

      // disable editing
      e.layer.toggleEdit();
    });
</script>

</body>
</html>