Editing/creating multipart features

1692
3
Jump to solution
08-15-2017 02:04 PM
SteveCole
Frequent Contributor

I have 3.x based app that allows my users to add features to a layer via the editing functionality and everything works great. One comment has come back to me about the possibility of creating one feature that represents multiple locations. In the desktop world, that would be a multipart feature:

I tried searching here for multipart but editing didn't come up. There are some addPath & removePath methods for polylines but that's all I've seen. Long story short- is it possible to create one feature that has multiple parts like my screenshot above? Are there any code examples about how to do that?

Thanks!

Steve

0 Kudos
1 Solution

Accepted Solutions
RobertScheitlin__GISP
MVP Emeritus

Steve,

   Here is a multi-part geometry draw toolbar example:

<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <meta name="viewport" content="width=device-width,user-scalable=no">

    <meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no">
    <title>Maps Toolbar</title>

    <link rel="stylesheet" href="https://js.arcgis.com/3.21/dijit/themes/nihilo/nihilo.css">
    <link rel="stylesheet" href="https://js.arcgis.com/3.21/esri/css/esri.css">
    <style>
      html, body, #mainWindow {
        font-family: sans-serif;
        height: 100%;
        width: 100%;
      }
      html, body {
        margin: 0;
        padding: 0;
      }
      #header {
        height: 80px;
        overflow: auto;
        padding: 0.5em;
      }
    </style>

    <script src="https://js.arcgis.com/3.21/"></script>
    <script>
      var map, toolbar, symbol, geomTask, lastTool, geomArray = [], multipart, gl;

      require([
        "esri/map",
        "esri/toolbars/draw",
        "esri/graphic",
        "esri/geometry/Polyline",
        "esri/geometry/Polygon",
        "esri/layers/GraphicsLayer",

        "dojo/parser", "dijit/registry",
        "dojo/_base/array", "dojo/on",

        "dijit/form/CheckBox",
        "dijit/layout/BorderContainer", "dijit/layout/ContentPane",
        "dijit/form/Button", "dijit/WidgetSet", "dojo/domReady!"
      ], function(
        Map, Draw, Graphic, Polyline, Polygon, GraphicsLayer,
        parser, registry, array, on
      ) {
        parser.parse();

        map = new Map("map", {
          basemap: "streets",
          center: [-15.469, 36.428],
          zoom: 3
        });

        map.on("load", createToolbar);

        // loop through all dijits, connect onClick event
        // listeners for buttons to activate drawing tools
        registry.forEach(function(d) {
          // d is a reference to a dijit
          // could be a layout container or a button
          if ( d.declaredClass === "dijit.form.Button" ) {
            d.on("click", activateTool);
          }
          if ( d.declaredClass === "dijit.form.CheckBox") {
            multipart = d;
            on(multipart, "change", function(){
              if(multipart.get('value')){
                registry.byId("finishBtn").set("disabled", false);
              }else{
                registry.byId("finishBtn").set("disabled", true);
              }
            });
          }
        });

        function activateTool() {
          var tool = this.label.toUpperCase().replace(/ /g, "_");
          if(tool === "FINISH_DRAWING" && multipart.get('value')){
            finishDrawing();
          }else{
            lastTool = tool;
            toolbar.activate(Draw[tool]);
            map.hideZoomSlider();
          }
        }

        function finishDrawing() {
          var graphic;
          switch (lastTool.toLowerCase()) {
            case "polyline":
              var polyline = new Polyline(map.spatialReference);
              array.map(geomArray, function(path){
                polyline.addPath(path);
              });
              symbol = toolbar.lineSymbol;
              graphic = new Graphic(polyline, symbol);
              gl.clear();
              map.graphics.add(graphic);
              break;
            default:
              var polygon = new Polygon(map.spatialReference);
              array.map(geomArray, function(ring){
                polygon.addRing(ring);
              });
              symbol = toolbar.fillSymbol;
              graphic = new Graphic(polygon, symbol);
              gl.clear();
              map.graphics.add(graphic);
              break;
          }
          geomArray = [];
          multipart.set('value', false);
          toolbar.deactivate();
          map.showZoomSlider();
        }

        function createToolbar(themap) {
          gl = new GraphicsLayer();
          map.addLayer(gl);
          toolbar = new Draw(map);
          toolbar.on("draw-end", addToMap);
        }

        function addToMap(evt) {
          var symbol;
          switch (evt.geometry.type) {
            case "polyline":
                if(multipart.get('value')){
                  geomArray.push(evt.geometry.paths[0]);
                }
              symbol = toolbar.lineSymbol;
              break;
            default:
              if(multipart.get('value')){
                geomArray.push(evt.geometry.rings[0]);
              }
              symbol = toolbar.fillSymbol;
              break;
          }
          var graphic = new Graphic(evt.geometry, symbol);

          if(multipart.get('value')){
            gl.add(graphic);
            return;
          }
          toolbar.deactivate();
          map.showZoomSlider();
          map.graphics.add(graphic);
        }
      });
    </script>
  </head>
  <body class="nihilo">

  <div id="mainWindow" data-dojo-type="dijit/layout/BorderContainer" data-dojo-props="design:'headline'">
    <div id="header" data-dojo-type="dijit/layout/ContentPane" data-dojo-props="region:'top'">
      <span>Draw:<br /></span>
      <input id="multipart" name="multipart" data-dojo-type="dijit/form/CheckBox"/> <label for="multipart">Draw Multi-part Geometry</label>
      <button data-dojo-type="dijit/form/Button">Polyline</button>
      <button data-dojo-type="dijit/form/Button">Polygon</button>
      <button id="finishBtn" name="finishBtn" data-dojo-type="dijit/form/Button" disabled="disabled">Finish Drawing</button>
    </div>
    <div id="map" data-dojo-type="dijit/layout/ContentPane" data-dojo-props="region:'center'"></div>
  </div>

  </body>
</html>
‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

View solution in original post

3 Replies
RobertScheitlin__GISP
MVP Emeritus

Steve,

   Here is a multi-part geometry draw toolbar example:

<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <meta name="viewport" content="width=device-width,user-scalable=no">

    <meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no">
    <title>Maps Toolbar</title>

    <link rel="stylesheet" href="https://js.arcgis.com/3.21/dijit/themes/nihilo/nihilo.css">
    <link rel="stylesheet" href="https://js.arcgis.com/3.21/esri/css/esri.css">
    <style>
      html, body, #mainWindow {
        font-family: sans-serif;
        height: 100%;
        width: 100%;
      }
      html, body {
        margin: 0;
        padding: 0;
      }
      #header {
        height: 80px;
        overflow: auto;
        padding: 0.5em;
      }
    </style>

    <script src="https://js.arcgis.com/3.21/"></script>
    <script>
      var map, toolbar, symbol, geomTask, lastTool, geomArray = [], multipart, gl;

      require([
        "esri/map",
        "esri/toolbars/draw",
        "esri/graphic",
        "esri/geometry/Polyline",
        "esri/geometry/Polygon",
        "esri/layers/GraphicsLayer",

        "dojo/parser", "dijit/registry",
        "dojo/_base/array", "dojo/on",

        "dijit/form/CheckBox",
        "dijit/layout/BorderContainer", "dijit/layout/ContentPane",
        "dijit/form/Button", "dijit/WidgetSet", "dojo/domReady!"
      ], function(
        Map, Draw, Graphic, Polyline, Polygon, GraphicsLayer,
        parser, registry, array, on
      ) {
        parser.parse();

        map = new Map("map", {
          basemap: "streets",
          center: [-15.469, 36.428],
          zoom: 3
        });

        map.on("load", createToolbar);

        // loop through all dijits, connect onClick event
        // listeners for buttons to activate drawing tools
        registry.forEach(function(d) {
          // d is a reference to a dijit
          // could be a layout container or a button
          if ( d.declaredClass === "dijit.form.Button" ) {
            d.on("click", activateTool);
          }
          if ( d.declaredClass === "dijit.form.CheckBox") {
            multipart = d;
            on(multipart, "change", function(){
              if(multipart.get('value')){
                registry.byId("finishBtn").set("disabled", false);
              }else{
                registry.byId("finishBtn").set("disabled", true);
              }
            });
          }
        });

        function activateTool() {
          var tool = this.label.toUpperCase().replace(/ /g, "_");
          if(tool === "FINISH_DRAWING" && multipart.get('value')){
            finishDrawing();
          }else{
            lastTool = tool;
            toolbar.activate(Draw[tool]);
            map.hideZoomSlider();
          }
        }

        function finishDrawing() {
          var graphic;
          switch (lastTool.toLowerCase()) {
            case "polyline":
              var polyline = new Polyline(map.spatialReference);
              array.map(geomArray, function(path){
                polyline.addPath(path);
              });
              symbol = toolbar.lineSymbol;
              graphic = new Graphic(polyline, symbol);
              gl.clear();
              map.graphics.add(graphic);
              break;
            default:
              var polygon = new Polygon(map.spatialReference);
              array.map(geomArray, function(ring){
                polygon.addRing(ring);
              });
              symbol = toolbar.fillSymbol;
              graphic = new Graphic(polygon, symbol);
              gl.clear();
              map.graphics.add(graphic);
              break;
          }
          geomArray = [];
          multipart.set('value', false);
          toolbar.deactivate();
          map.showZoomSlider();
        }

        function createToolbar(themap) {
          gl = new GraphicsLayer();
          map.addLayer(gl);
          toolbar = new Draw(map);
          toolbar.on("draw-end", addToMap);
        }

        function addToMap(evt) {
          var symbol;
          switch (evt.geometry.type) {
            case "polyline":
                if(multipart.get('value')){
                  geomArray.push(evt.geometry.paths[0]);
                }
              symbol = toolbar.lineSymbol;
              break;
            default:
              if(multipart.get('value')){
                geomArray.push(evt.geometry.rings[0]);
              }
              symbol = toolbar.fillSymbol;
              break;
          }
          var graphic = new Graphic(evt.geometry, symbol);

          if(multipart.get('value')){
            gl.add(graphic);
            return;
          }
          toolbar.deactivate();
          map.showZoomSlider();
          map.graphics.add(graphic);
        }
      });
    </script>
  </head>
  <body class="nihilo">

  <div id="mainWindow" data-dojo-type="dijit/layout/BorderContainer" data-dojo-props="design:'headline'">
    <div id="header" data-dojo-type="dijit/layout/ContentPane" data-dojo-props="region:'top'">
      <span>Draw:<br /></span>
      <input id="multipart" name="multipart" data-dojo-type="dijit/form/CheckBox"/> <label for="multipart">Draw Multi-part Geometry</label>
      <button data-dojo-type="dijit/form/Button">Polyline</button>
      <button data-dojo-type="dijit/form/Button">Polygon</button>
      <button id="finishBtn" name="finishBtn" data-dojo-type="dijit/form/Button" disabled="disabled">Finish Drawing</button>
    </div>
    <div id="map" data-dojo-type="dijit/layout/ContentPane" data-dojo-props="region:'center'"></div>
  </div>

  </body>
</html>
‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
SteveCole
Frequent Contributor

Awesome. Great to know that it is possible. Thanks for the sample. It seems a little awkward to implement but I think I have an idea of how to do it. Thanks again!

0 Kudos
MarcGraham2
Occasional Contributor III

Hi Robert,

I don't suppose you have any interest in extending your above example to apply edits to a feature service?

Kind regards,

Marc

0 Kudos