Editable ArcGIS REST Feature Service

This example uses OpenLayers v4.0.1. The latest is v.

#### Editable ArcGIS REST Feature Service

Draw or modify

Example of using an ArcGIS REST Feature Service in an editing application.

This example loads features from ArcGIS REST Feature Service and allows to add new features or update existing features.

Related API documentation:

- ol.Map
,
- ol.View
,
- ol.format.EsriJSON
,
- ol.interaction
,
- ol.interaction.Draw
,
- ol.interaction.Modify
,
- ol.interaction.Select
,
- ol.layer.Tile
,
- ol.layer.Vector
,
- ol.loadingstrategy
,
- ol.proj
,
- ol.source.Vector
,
- ol.source.XYZ
,
- ol.tilegrid

Copy Edit
Editable ArcGIS REST Feature Service Example of using an ArcGIS REST Feature Service in an editing application. var serviceUrl = 'https://services.arcgis.com/rOo16HdIMeOBI4Mb/arcgis/rest/' + 'services/PDX_Pedestrian_Districts/FeatureServer/'; var layer = '0'; var esrijsonFormat = new ol.format.EsriJSON(); var vectorSource = new ol.source.Vector({ loader: function(extent, resolution, projection) { var url = serviceUrl + layer + '/query/?f=json&' + 'returnGeometry=true&spatialRel=esriSpatialRelIntersects&geometry=' + encodeURIComponent('{"xmin":' + extent[0] + ',"ymin":' + extent[1] + ',"xmax":' + extent[2] + ',"ymax":' + extent[3] + ',"spatialReference":{"wkid":102100}}') + '&geometryType=esriGeometryEnvelope&inSR=102100&outFields=*' + '&outSR=102100'; $.ajax({url: url, dataType: 'jsonp', success: function(response) { if (response.error) { alert(response.error.message + '\n' + response.error.details.join('\n')); } else { // dataProjection will be read from document var features = esrijsonFormat.readFeatures(response, { featureProjection: projection }); if (features.length > 0) { vectorSource.addFeatures(features); } } }}); }, strategy: ol.loadingstrategy.tile(ol.tilegrid.createXYZ({ tileSize: 512 })) }); var vector = new ol.layer.Vector({ source: vectorSource }); var raster = new ol.layer.Tile({ source: new ol.source.XYZ({ attributions: 'Tiles © <a href="https://services.arcgisonline.com/ArcGIS/' + 'rest/services/World_Topo_Map/MapServer">ArcGIS</a>', url: 'https://server.arcgisonline.com/ArcGIS/rest/services/' + 'World_Topo_Map/MapServer/tile/{z}/{y}/{x}' }) }); var draw = new ol.interaction.Draw({ source: vectorSource, type: /** @type {ol.geom.GeometryType} */ ('Polygon') }); var select = new ol.interaction.Select(); select.setActive(false); var selected = select.getFeatures(); var modify = new ol.interaction.Modify({ features: selected }); modify.setActive(false); var map = new ol.Map({ interactions: ol.interaction.defaults().extend([draw, select, modify]), layers: [raster, vector], target: document.getElementById('map'), view: new ol.View({ center: ol.proj.transform([-122.619, 45.512], 'EPSG:4326', 'EPSG:3857'), zoom: 12 }) }); var typeSelect = document.getElementById('type'); /** * Let user change the interaction type. */ typeSelect.onchange = function() { draw.setActive(typeSelect.value === 'DRAW'); select.setActive(typeSelect.value === 'MODIFY'); modify.setActive(typeSelect.value === 'MODIFY'); }; var dirty = {}; selected.on('add', function(evt) { var feature = evt.element; feature.on('change', function(evt) { dirty[evt.target.getId()] = true; }); }); selected.on('remove', function(evt) { var feature = evt.element; var fid = feature.getId(); if (dirty[fid] === true) { var payload = '[' + esrijsonFormat.writeFeature(feature, { featureProjection: map.getView().getProjection() }) + ']'; var url = serviceUrl + layer + '/updateFeatures'; $.post(url, {f: 'json', features: payload}).done(function(data) { var result = JSON.parse(data); if (result.updateResults && result.updateResults.length > 0) { if (result.updateResults[0].success !== true) { var error = result.updateResults[0].error; alert(error.description + ' (' + error.code + ')'); } else { delete dirty[fid]; } } }); } }); draw.on('drawend', function(evt) { var feature = evt.feature; var payload = '[' + esrijsonFormat.writeFeature(feature, { featureProjection: map.getView().getProjection() }) + ']'; var url = serviceUrl + layer + '/addFeatures'; $.post(url, {f: 'json', features: payload}).done(function(data) { var result = JSON.parse(data); if (result.addResults && result.addResults.length > 0) { if (result.addResults[0].success === true) { feature.setId(result.addResults[0]['objectId']); vectorSource.clear(); } else { var error = result.addResults[0].error; alert(error.description + ' (' + error.code + ')'); } } }); }); <div id="map" class="map"></div> <form class="form-inline"> <label>Draw or modify &nbsp;</label> <select id="type"> <option value="DRAW">Draw</option> <option value="MODIFY">Modify</option> </select> </form>

    <!DOCTYPE html>
    <html>
      <head>
        <title>Editable ArcGIS REST Feature Service</title>
        <link rel="stylesheet" href="https://openlayers.org/en/v4.0.1/css/ol.css" type="text/css">
        <!-- The line below is only needed for old environments like Internet Explorer and Android 4.x -->
        <script src="https://cdn.polyfill.io/v2/polyfill.min.js?features=requestAnimationFrame,Element.prototype.classList,URL"></script>
        <script src="https://openlayers.org/en/v4.0.1/build/ol.js"></script>
        <script src="https://code.jquery.com/jquery-2.2.3.min.js"></script>
      </head>
      <body>
        <div id="map" class="map"></div>
        <form class="form-inline">
          <label>Draw or modify &nbsp;</label>
          <select id="type">
            <option value="DRAW">Draw</option>
            <option value="MODIFY">Modify</option>
          </select>
        </form>
        <script>
          var serviceUrl = 'https://services.arcgis.com/rOo16HdIMeOBI4Mb/arcgis/rest/' +
              'services/PDX_Pedestrian_Districts/FeatureServer/';
          var layer = '0';

          var esrijsonFormat = new ol.format.EsriJSON();

          var vectorSource = new ol.source.Vector({
            loader: function(extent, resolution, projection) {
              var url = serviceUrl + layer + '/query/?f=json&' +
                  'returnGeometry=true&spatialRel=esriSpatialRelIntersects&geometry=' +
                  encodeURIComponent('{"xmin":' + extent[0] + ',"ymin":' +
                      extent[1] + ',"xmax":' + extent[2] + ',"ymax":' + extent[3] +
                      ',"spatialReference":{"wkid":102100}}') +
                  '&geometryType=esriGeometryEnvelope&inSR=102100&outFields=*' +
                  '&outSR=102100';
              $.ajax({url: url, dataType: 'jsonp', success: function(response) {
                if (response.error) {
                  alert(response.error.message + '\n' +
                      response.error.details.join('\n'));
                } else {
                  // dataProjection will be read from document
                  var features = esrijsonFormat.readFeatures(response, {
                    featureProjection: projection
                  });
                  if (features.length > 0) {
                    vectorSource.addFeatures(features);
                  }
                }
              }});
            },
            strategy: ol.loadingstrategy.tile(ol.tilegrid.createXYZ({
              tileSize: 512
            }))
          });

          var vector = new ol.layer.Vector({
            source: vectorSource
          });

          var raster = new ol.layer.Tile({
            source: new ol.source.XYZ({
              attributions: 'Tiles © <a href="https://services.arcgisonline.com/ArcGIS/' +
                  'rest/services/World_Topo_Map/MapServer">ArcGIS</a>',
              url: 'https://server.arcgisonline.com/ArcGIS/rest/services/' +
                  'World_Topo_Map/MapServer/tile/{z}/{y}/{x}'
            })
          });

          var draw = new ol.interaction.Draw({
            source: vectorSource,
            type: /** @type {ol.geom.GeometryType} */ ('Polygon')
          });

          var select = new ol.interaction.Select();
          select.setActive(false);
          var selected = select.getFeatures();

          var modify = new ol.interaction.Modify({
            features: selected
          });
          modify.setActive(false);

          var map = new ol.Map({
            interactions: ol.interaction.defaults().extend([draw, select, modify]),
            layers: [raster, vector],
            target: document.getElementById('map'),
            view: new ol.View({
              center: ol.proj.transform([-122.619, 45.512], 'EPSG:4326', 'EPSG:3857'),
              zoom: 12
            })
          });

          var typeSelect = document.getElementById('type');

          /**
           * Let user change the interaction type.
           */
          typeSelect.onchange = function() {
            draw.setActive(typeSelect.value === 'DRAW');
            select.setActive(typeSelect.value === 'MODIFY');
            modify.setActive(typeSelect.value === 'MODIFY');
          };

          var dirty = {};

          selected.on('add', function(evt) {
            var feature = evt.element;
            feature.on('change', function(evt) {
              dirty[evt.target.getId()] = true;
            });
          });

          selected.on('remove', function(evt) {
            var feature = evt.element;
            var fid = feature.getId();
            if (dirty[fid] === true) {
              var payload = '[' + esrijsonFormat.writeFeature(feature, {
                featureProjection: map.getView().getProjection()
              }) + ']';
              var url = serviceUrl + layer + '/updateFeatures';
              $.post(url, {f: 'json', features: payload}).done(function(data) {
                var result = JSON.parse(data);
                if (result.updateResults && result.updateResults.length > 0) {
                  if (result.updateResults[0].success !== true) {
                    var error = result.updateResults[0].error;
                    alert(error.description + ' (' + error.code + ')');
                  } else {
                    delete dirty[fid];
                  }
                }
              });
            }
          });

          draw.on('drawend', function(evt) {
            var feature = evt.feature;
            var payload = '[' + esrijsonFormat.writeFeature(feature, {
              featureProjection: map.getView().getProjection()
            }) + ']';
            var url = serviceUrl + layer + '/addFeatures';
            $.post(url, {f: 'json', features: payload}).done(function(data) {
              var result = JSON.parse(data);
              if (result.addResults && result.addResults.length > 0) {
                if (result.addResults[0].success === true) {
                  feature.setId(result.addResults[0]['objectId']);
                  vectorSource.clear();
                } else {
                  var error = result.addResults[0].error;
                  alert(error.description + ' (' + error.code + ')');
                }
              }
            });
          });
        </script>
      </body>
    </html>