Applying a Query Spatial Relationship for Custom Dropdown list on Attribute Inspector

912
5
Jump to solution
03-13-2018 11:30 AM
GiovanniMarrero3
New Contributor III

Hello,

I have been trying to modify the attribute inspector to only include attributes on the drop down list that surround the feature that was clicked. This will help so that users make areas contiguously without breaks (making islands). 

Here is my fiddle

I have tried using this method 

selectQuery.spatialRelationship = Query.SPATIAL_REL_TOUCHES;

but I have not been successful. 

Any help would be valuable. 

0 Kudos
1 Solution

Accepted Solutions
RobertScheitlin__GISP
MVP Emeritus

Giovanni,

Here is my code changes to get you back to where you were (i.e. changes not actually getting applied to FeatureServer service). I am not sure why the FeatureLayer.applyEdits is failing.

<!DOCTYPE html>
<html>

<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">

  <meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no">
  <title>Unique Value Renderer</title>
  <link rel="stylesheet" href="https://js.arcgis.com/3.23/esri/css/esri.css">
  <link rel="stylesheet" href="https://js.arcgis.com/3.23/dijit/themes/claro/claro.css">
  <style>
    html,
    body,
    #mapDiv {
      height: 100%;
      margin: 0;
      padding: 0;
    }

    .templatePicker {
      border: none;
    }

    .dj_ie .infowindow .window .top .right .user .content {
      position: relative;
    }

    .dj_ie .simpleInfoWindow .content {
      position: relative;
    }

    .esriAttributeInspector .atiLayerName {
      display: none;
    }
  </style>
  <script src="https://js.arcgis.com/3.23/"></script>
  <script>
    var map, updateFeature, uNames, unique;
    require([
      "esri/map", "esri/layers/FeatureLayer", "esri/dijit/AttributeInspector",
      "esri/symbols/SimpleLineSymbol", "esri/symbols/SimpleFillSymbol",
      "esri/renderers/UniqueValueRenderer", "esri/Color", "esri/config",
      "esri/tasks/query", "dojo/_base/array", "dijit/registry", "dojo/query",
      "dojo/store/Memory", "dojo/dom-construct", "dijit/form/Button",
      "dojo/domReady!"
    ], function(
      Map, FeatureLayer, AttributeInspector,
      SimpleLineSymbol, SimpleFillSymbol,
      UniqueValueRenderer, Color, esriConfig,
      Query, array, registry, dojoQuery,
      Memory, domConstruct, Button
    ) {

      esriConfig.defaults.io.proxyUrl = "/proxy/";

      map = new Map("mapDiv", {
        basemap: "topo",
        center: [-84.20, 33.78], // lon, lat
        zoom: 11
      });

      var defaultSymbol = new SimpleFillSymbol().setStyle(SimpleFillSymbol.STYLE_NULL);
      defaultSymbol.outline.setStyle(SimpleLineSymbol.STYLE_NULL);

      //create renderer
      var renderer = new UniqueValueRenderer(defaultSymbol, "ES_Name");

      //add symbol for each possible value
      renderer.addValue("North", new SimpleFillSymbol().setColor(new Color([255, 0, 0, 0.5])));
      renderer.addValue("South", new SimpleFillSymbol().setColor(new Color([0, 255, 0, 0.5])));
      renderer.addValue("East", new SimpleFillSymbol().setColor(new Color([0, 0, 255, 0.5])));
      renderer.addValue("West", new SimpleFillSymbol().setColor(new Color([255, 0, 255, 0.5])));
      renderer.addValue("NWest", new SimpleFillSymbol().setColor(new Color([255, 255, 0, 0.5])));
      renderer.addValue("SEast", new SimpleFillSymbol().setColor(new Color([0, 255, 255, 0.5])));
      renderer.addValue("NEast", new SimpleFillSymbol().setColor(new Color([255, 255, 0, 0.5])));
      renderer.addValue("SWest", new SimpleFillSymbol().setColor(new Color([0, 0, 0, 0.5])));

      var blocks = new FeatureLayer("http://gis.dekalb.k12.ga.us/arcgis_webadapter/rest/services/Redistricting/ES_Areas_Redist_Test/Featu...", {
        mode: FeatureLayer.MODE_SNAPSHOT,
        outFields: ["*"]
      });
      var selectionSymbol = new SimpleFillSymbol().setColor(new Color([0,255,0,0.5]));
      blocks.setSelectionSymbol(selectionSymbol);

      blocks.setRenderer(renderer);
      map.addLayers([blocks]);

      map.on("layers-add-result", initSelectToolbar);

      map.infoWindow.on('show', function(evt) {
        setTimeout(function() {
          var node = dojoQuery('.atiField', evt.domNode);
          if (!node) {
            return;
          }
          var selectWid = registry.getEnclosingWidget(node[1]);
          //console.info(selectWid.get("store"));
          var oNames = [];
          array.map(uNames, function(fName){
            oNames.push({id: fName, name: fName});
          });
          var data = {
            label: 'name',
            items: oNames
          };
          var store = new Memory({
            data: data
          });
          selectWid.setAttribute("store", store);
        }, 800);
      });

      function initSelectToolbar(evt) {
        var blocks = evt.layers[0].layer;
        var selectQuery = new Query();

        map.on("click", function(evt) {
          map.infoWindow.hide();
          selectQuery.outFields = ["*"];
          selectQuery.geometry = evt.mapPoint;
          selectQuery.returnGeometry = true;
          blocks.selectFeatures(selectQuery, FeatureLayer.SELECTION_NEW, function(features) {
            uNames = [];
            if (features.length > 0) {
              var attrQuery = new Query();
              attrQuery.geometry = features[0].geometry;
              attrQuery.outFields = ["ES_Name"];
              attrQuery.returnGeometry = false;
              attrQuery.spatialRelationship = Query.SPATIAL_REL_TOUCHES;
              blocks.queryFeatures(attrQuery, function(fset) {
                array.map(fset.features, function(feat) {
                  var fname = feat.attributes.ES_Name;
                  if(uNames.indexOf(fname) === -1){
                    uNames.push(fname);
                  }
                });
              });
              //store the current feature
              updateFeature = features[0];
              map.infoWindow.setTitle(features[0].getLayer().name);
              map.infoWindow.show(evt.screenPoint, map.getInfoWindowAnchor(evt.screenPoint));
            } else {
              map.infoWindow.hide();
            }
          });
        });

        map.infoWindow.on("hide", function() {
          blocks.clearSelection();
        });

        var layerInfos = [{
          'featureLayer': blocks,
          'showAttachments': false,
          'isEditable': true,
          'fieldInfos': [{
              'fieldName': 'ES_Name',
              'isEditable': false,
              'label': 'Current School:'
            },
            {
              'fieldName': 'ES_Name',
              'isEditable': true,
              'label': 'Proposed School:'
            }
          ]
        }];

        //Initialize Attribute Inspector
        var attInspector = new AttributeInspector({
          layerInfos: layerInfos
        }, domConstruct.create("div"));

        //add a save button next to the delete button
        var saveButton = new Button({
          label: "Apply",
          "class": "saveButton"
        }, domConstruct.create("div"));
        domConstruct.place(saveButton.domNode, attInspector.deleteBtn.domNode, "after");

        saveButton.on("click", function() {
          updateFeature.getLayer().applyEdits(null, [updateFeature], null, function(result){
            console.log(result);
            map.infoWindow.hide();
          }, function(error){
            console.log(error);
          });
        });

        attInspector.on("attribute-change", function(evt) {
          //store the updates to apply when the save button is clicked
          updateFeature.attributes[evt.fieldName] = evt.fieldValue;
        });

        map.infoWindow.setContent(attInspector.domNode);
        map.infoWindow.resize(350, 240);
      }

    });
  </script>
</head>

<body class="claro">
  <div id="mapDiv"></div>
</body>

</html>

View solution in original post

0 Kudos
5 Replies
RobertScheitlin__GISP
MVP Emeritus

Giovanni,

   Here is your code modified to accomplish what you are after:

<!DOCTYPE html>
<html>

<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">

  <meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no">
  <title>Unique Value Renderer</title>
  <link rel="stylesheet" href="https://js.arcgis.com/3.23/esri/css/esri.css">
  <link rel="stylesheet" href="https://js.arcgis.com/3.23/dijit/themes/claro/claro.css">
  <style>
    html,
    body,
    #mapDiv {
      height: 100%;
      margin: 0;
      padding: 0;
    }

    .templatePicker {
      border: none;
    }

    .dj_ie .infowindow .window .top .right .user .content {
      position: relative;
    }

    .dj_ie .simpleInfoWindow .content {
      position: relative;
    }

    .esriAttributeInspector .atiLayerName {
      display: none;
    }
  </style>
  <script src="https://js.arcgis.com/3.23/"></script>
  <script>
    var map, updateFeature, uNames, unique;
    require([
      "esri/map", "esri/layers/FeatureLayer", "esri/dijit/AttributeInspector",
      "esri/symbols/SimpleLineSymbol", "esri/symbols/SimpleFillSymbol",
      "esri/renderers/UniqueValueRenderer", "esri/Color", "esri/config",
      "esri/tasks/query", "dojo/_base/array", "dijit/registry", "dojo/query",
      "dojo/data/ItemFileReadStore", "dojo/dom-construct", "dijit/form/Button",
      "dojo/domReady!"
    ], function(
      Map, FeatureLayer, AttributeInspector,
      SimpleLineSymbol, SimpleFillSymbol,
      UniqueValueRenderer, Color, esriConfig,
      Query, array, registry, dojoQuery,
      ItemFileReadStore, domConstruct, Button
    ) {

      esriConfig.defaults.io.proxyUrl = "/proxy/";

      map = new Map("mapDiv", {
        basemap: "topo",
        center: [-84.20, 33.78], // lon, lat
        zoom: 11
      });

      var defaultSymbol = new SimpleFillSymbol().setStyle(SimpleFillSymbol.STYLE_NULL);
      defaultSymbol.outline.setStyle(SimpleLineSymbol.STYLE_NULL);

      //create renderer
      var renderer = new UniqueValueRenderer(defaultSymbol, "ES_Name");

      //add symbol for each possible value
      renderer.addValue("North", new SimpleFillSymbol().setColor(new Color([255, 0, 0, 0.5])));
      renderer.addValue("South", new SimpleFillSymbol().setColor(new Color([0, 255, 0, 0.5])));
      renderer.addValue("East", new SimpleFillSymbol().setColor(new Color([0, 0, 255, 0.5])));
      renderer.addValue("West", new SimpleFillSymbol().setColor(new Color([255, 0, 255, 0.5])));
      renderer.addValue("NWest", new SimpleFillSymbol().setColor(new Color([255, 255, 0, 0.5])));
      renderer.addValue("SEast", new SimpleFillSymbol().setColor(new Color([0, 255, 255, 0.5])));
      renderer.addValue("NEast", new SimpleFillSymbol().setColor(new Color([255, 255, 0, 0.5])));
      renderer.addValue("SWest", new SimpleFillSymbol().setColor(new Color([0, 0, 0, 0.5])));

      var blocks = new FeatureLayer("http://gis.dekalb.k12.ga.us/arcgis_webadapter/rest/services/Redistricting/ES_Areas_Redist_Test/Featu...", {
        mode: FeatureLayer.MODE_SNAPSHOT,
        outFields: ["ES_Name"]
      });
      var selectionSymbol = new SimpleFillSymbol().setColor(new Color([255,255,0,0.5]));
      blocks.setSelectionSymbol(selectionSymbol);

      blocks.setRenderer(renderer);
      map.addLayers([blocks]);

      map.on("layers-add-result", initSelectToolbar);

      map.infoWindow.on('show', function(evt) {
        setTimeout(function() {
          var node = dojoQuery('.atiField', evt.domNode);
          if (!node) {
            return;
          }
          var selectWid = registry.getEnclosingWidget(node[1]);
          var oNames = [];
          array.map(uNames, function(fName){
            oNames.push({name: fName});
          });
          var data = {
            label: 'name',
            items: oNames
          };
          var store = new ItemFileReadStore({
            data: data
          });
          selectWid.setAttribute("store", store);
        }, 800);
      });

      function initSelectToolbar(evt) {
        var blocks = evt.layers[0].layer;
        var selectQuery = new Query();

        map.on("click", function(evt) {
          map.infoWindow.hide();
          selectQuery.geometry = evt.mapPoint;
          selectQuery.returnGeometry = true;
          blocks.selectFeatures(selectQuery, FeatureLayer.SELECTION_NEW, function(features) {
            uNames = [];
            if (features.length > 0) {
              var attrQuery = new Query();
              attrQuery.geometry = features[0].geometry;
              attrQuery.outFields = ["ES_Name"];
              attrQuery.returnGeometry = false;
              attrQuery.spatialRelationship = Query.SPATIAL_REL_TOUCHES;
              blocks.queryFeatures(attrQuery, function(fset) {
                array.map(fset.features, function(feat) {
                  var fname = feat.attributes.ES_Name;
                  if(uNames.indexOf(fname) === -1){
                    uNames.push(fname);
                  }
                });
              });
              //store the current feature
              updateFeature = features[0];
              map.infoWindow.setTitle(features[0].getLayer().name);
              map.infoWindow.show(evt.screenPoint, map.getInfoWindowAnchor(evt.screenPoint));
            } else {
              map.infoWindow.hide();
            }
          });
        });

        map.infoWindow.on("hide", function() {
          blocks.clearSelection();
        });

        var layerInfos = [{
          'featureLayer': blocks,
          'showAttachments': false,
          'isEditable': true,
          'fieldInfos': [{
              'fieldName': 'ES_Name',
              'isEditable': false,
              'label': 'Current School:'
            },
            {
              'fieldName': 'ES_Name',
              'isEditable': true,
              'label': 'Proposed School:'
            }
          ]
        }];

        //Initialize Attribute Inspector
        var attInspector = new AttributeInspector({
          layerInfos: layerInfos
        }, domConstruct.create("div"));

        //add a save button next to the delete button
        var saveButton = new Button({
          label: "Apply",
          "class": "saveButton"
        }, domConstruct.create("div"));
        domConstruct.place(saveButton.domNode, attInspector.deleteBtn.domNode, "after");

        saveButton.on("click", function() {
          updateFeature.getLayer().applyEdits(null, [updateFeature], null);
        });

        attInspector.on("attribute-change", function(evt) {
          //store the updates to apply when the save button is clicked
          updateFeature.attributes[evt.fieldName] = evt.fieldValue;
        });

        map.infoWindow.setContent(attInspector.domNode);
        map.infoWindow.resize(350, 240);
      }

    });
  </script>
</head>

<body class="claro">
  <div id="mapDiv"></div>
</body>

</html>
GiovanniMarrero3
New Contributor III

Thank you Robert. 

The drop down query is working as requested, however when the user picks one or any of the drop down selection, the feature disappears becoming 100% transparent. As if the attribute selection is not recognized and saved correctly.  

http://jsfiddle.net/7jsvsfa9/

0 Kudos
RobertScheitlin__GISP
MVP Emeritus

Giovanni,

   Were you getting edits to apply back to your data in your original code?

0 Kudos
RobertScheitlin__GISP
MVP Emeritus

Giovanni,

Here is my code changes to get you back to where you were (i.e. changes not actually getting applied to FeatureServer service). I am not sure why the FeatureLayer.applyEdits is failing.

<!DOCTYPE html>
<html>

<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">

  <meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no">
  <title>Unique Value Renderer</title>
  <link rel="stylesheet" href="https://js.arcgis.com/3.23/esri/css/esri.css">
  <link rel="stylesheet" href="https://js.arcgis.com/3.23/dijit/themes/claro/claro.css">
  <style>
    html,
    body,
    #mapDiv {
      height: 100%;
      margin: 0;
      padding: 0;
    }

    .templatePicker {
      border: none;
    }

    .dj_ie .infowindow .window .top .right .user .content {
      position: relative;
    }

    .dj_ie .simpleInfoWindow .content {
      position: relative;
    }

    .esriAttributeInspector .atiLayerName {
      display: none;
    }
  </style>
  <script src="https://js.arcgis.com/3.23/"></script>
  <script>
    var map, updateFeature, uNames, unique;
    require([
      "esri/map", "esri/layers/FeatureLayer", "esri/dijit/AttributeInspector",
      "esri/symbols/SimpleLineSymbol", "esri/symbols/SimpleFillSymbol",
      "esri/renderers/UniqueValueRenderer", "esri/Color", "esri/config",
      "esri/tasks/query", "dojo/_base/array", "dijit/registry", "dojo/query",
      "dojo/store/Memory", "dojo/dom-construct", "dijit/form/Button",
      "dojo/domReady!"
    ], function(
      Map, FeatureLayer, AttributeInspector,
      SimpleLineSymbol, SimpleFillSymbol,
      UniqueValueRenderer, Color, esriConfig,
      Query, array, registry, dojoQuery,
      Memory, domConstruct, Button
    ) {

      esriConfig.defaults.io.proxyUrl = "/proxy/";

      map = new Map("mapDiv", {
        basemap: "topo",
        center: [-84.20, 33.78], // lon, lat
        zoom: 11
      });

      var defaultSymbol = new SimpleFillSymbol().setStyle(SimpleFillSymbol.STYLE_NULL);
      defaultSymbol.outline.setStyle(SimpleLineSymbol.STYLE_NULL);

      //create renderer
      var renderer = new UniqueValueRenderer(defaultSymbol, "ES_Name");

      //add symbol for each possible value
      renderer.addValue("North", new SimpleFillSymbol().setColor(new Color([255, 0, 0, 0.5])));
      renderer.addValue("South", new SimpleFillSymbol().setColor(new Color([0, 255, 0, 0.5])));
      renderer.addValue("East", new SimpleFillSymbol().setColor(new Color([0, 0, 255, 0.5])));
      renderer.addValue("West", new SimpleFillSymbol().setColor(new Color([255, 0, 255, 0.5])));
      renderer.addValue("NWest", new SimpleFillSymbol().setColor(new Color([255, 255, 0, 0.5])));
      renderer.addValue("SEast", new SimpleFillSymbol().setColor(new Color([0, 255, 255, 0.5])));
      renderer.addValue("NEast", new SimpleFillSymbol().setColor(new Color([255, 255, 0, 0.5])));
      renderer.addValue("SWest", new SimpleFillSymbol().setColor(new Color([0, 0, 0, 0.5])));

      var blocks = new FeatureLayer("http://gis.dekalb.k12.ga.us/arcgis_webadapter/rest/services/Redistricting/ES_Areas_Redist_Test/Featu...", {
        mode: FeatureLayer.MODE_SNAPSHOT,
        outFields: ["*"]
      });
      var selectionSymbol = new SimpleFillSymbol().setColor(new Color([0,255,0,0.5]));
      blocks.setSelectionSymbol(selectionSymbol);

      blocks.setRenderer(renderer);
      map.addLayers([blocks]);

      map.on("layers-add-result", initSelectToolbar);

      map.infoWindow.on('show', function(evt) {
        setTimeout(function() {
          var node = dojoQuery('.atiField', evt.domNode);
          if (!node) {
            return;
          }
          var selectWid = registry.getEnclosingWidget(node[1]);
          //console.info(selectWid.get("store"));
          var oNames = [];
          array.map(uNames, function(fName){
            oNames.push({id: fName, name: fName});
          });
          var data = {
            label: 'name',
            items: oNames
          };
          var store = new Memory({
            data: data
          });
          selectWid.setAttribute("store", store);
        }, 800);
      });

      function initSelectToolbar(evt) {
        var blocks = evt.layers[0].layer;
        var selectQuery = new Query();

        map.on("click", function(evt) {
          map.infoWindow.hide();
          selectQuery.outFields = ["*"];
          selectQuery.geometry = evt.mapPoint;
          selectQuery.returnGeometry = true;
          blocks.selectFeatures(selectQuery, FeatureLayer.SELECTION_NEW, function(features) {
            uNames = [];
            if (features.length > 0) {
              var attrQuery = new Query();
              attrQuery.geometry = features[0].geometry;
              attrQuery.outFields = ["ES_Name"];
              attrQuery.returnGeometry = false;
              attrQuery.spatialRelationship = Query.SPATIAL_REL_TOUCHES;
              blocks.queryFeatures(attrQuery, function(fset) {
                array.map(fset.features, function(feat) {
                  var fname = feat.attributes.ES_Name;
                  if(uNames.indexOf(fname) === -1){
                    uNames.push(fname);
                  }
                });
              });
              //store the current feature
              updateFeature = features[0];
              map.infoWindow.setTitle(features[0].getLayer().name);
              map.infoWindow.show(evt.screenPoint, map.getInfoWindowAnchor(evt.screenPoint));
            } else {
              map.infoWindow.hide();
            }
          });
        });

        map.infoWindow.on("hide", function() {
          blocks.clearSelection();
        });

        var layerInfos = [{
          'featureLayer': blocks,
          'showAttachments': false,
          'isEditable': true,
          'fieldInfos': [{
              'fieldName': 'ES_Name',
              'isEditable': false,
              'label': 'Current School:'
            },
            {
              'fieldName': 'ES_Name',
              'isEditable': true,
              'label': 'Proposed School:'
            }
          ]
        }];

        //Initialize Attribute Inspector
        var attInspector = new AttributeInspector({
          layerInfos: layerInfos
        }, domConstruct.create("div"));

        //add a save button next to the delete button
        var saveButton = new Button({
          label: "Apply",
          "class": "saveButton"
        }, domConstruct.create("div"));
        domConstruct.place(saveButton.domNode, attInspector.deleteBtn.domNode, "after");

        saveButton.on("click", function() {
          updateFeature.getLayer().applyEdits(null, [updateFeature], null, function(result){
            console.log(result);
            map.infoWindow.hide();
          }, function(error){
            console.log(error);
          });
        });

        attInspector.on("attribute-change", function(evt) {
          //store the updates to apply when the save button is clicked
          updateFeature.attributes[evt.fieldName] = evt.fieldValue;
        });

        map.infoWindow.setContent(attInspector.domNode);
        map.infoWindow.resize(350, 240);
      }

    });
  </script>
</head>

<body class="claro">
  <div id="mapDiv"></div>
</body>

</html>
0 Kudos
GiovanniMarrero3
New Contributor III

That's it, nailed it!

Thanks for the help.

0 Kudos