Select graphics within a graphics layer

9900
4
Jump to solution
02-06-2014 11:11 AM
BrandonIves
New Contributor
I am trying to select specific graphics point features that I am adding through code. I can't seem to figure out how to grab the individual graphics withing the graphics layer. Any help is appreciated.

/// <reference path="index.html" />
var mapMain, selectionLayer, graphicsLayer, selectionToolbar, graphic, defaultSymbol, highlightSymbol, simpleMarkerSymbol, resultTemplate;

require([
  "esri/map",
  "esri/geometry/Extent",
  "esri/layers/ArcGISTiledMapServiceLayer",
  "esri/layers/FeatureLayer",
  "esri/tasks/GeometryService",
  "esri/tasks/query",
  "esri/tasks/QueryTask",
  "esri/tasks/FeatureSet",
  "esri/graphic",
  "esri/toolbars/draw",
  "esri/config",

  "dojo/ready",
  "dojo/parser",
  "dojo/on",
  "dojo/_base/array",

  "dijit/layout/BorderContainer",
  "dijit/layout/ContentPane"],
  function (
    Map, Extent, ArcGISTiledMapServiceLayer, FeatureLayer,
    GeometryService, Query, QueryTask, FeatureSet, graphic, draw, config,
    ready, parser, on, array, BorderContainer, ContentPane
    ) {

      ready(function () {

          // Create the map
          mapMain = new Map("cpCenter")
          var layerURL = "http://gisaprd/ArcGIS/rest/services/BaseMap_ArcReader_Cached/MapServer";
          myLayer = new esri.layers.ArcGISTiledMapServiceLayer(layerURL, { "opacity": 0.5 });
          mapMain.addLayer(myLayer);

          dojo.connect(mapMain, "onLoad", initSelectToolbar);
          //dojo.connect(mapMain, "onLoad", function () {
          //    selectionLayer = new esri.layers.GraphicsLayer();
          //    mapMain.addLayer(selectionLayer);
          //});

          var queryTask = new QueryTask("http://gisaprd/ArcGIS/rest/services/SRSOutageTest/MapServer/3");

          var query = new Query();
          query.returnGeometry = false;
          query.outFields = ["*"];
          query.where = "GIS_X IS NOT NULL";
          queryTask.execute(query, showResults, errBack);

         

          simpleMarkerSymbol = new esri.symbol.SimpleMarkerSymbol().setColor(new dojo.Color([0,255,255]));
          defaultSymbol = new esri.symbol.SimpleMarkerSymbol().setColor(new dojo.Color([0, 0, 255]));
          highlightSymbol = new esri.symbol.SimpleMarkerSymbol().setColor(new dojo.Color([255, 0, 0]));
      });
      //initialize drawing toolbar
      function initSelectToolbar(mapMain) {
          selectionToolbar = new esri.toolbars.Draw(mapMain);

          //find points in Extent when user completes drawing extent
          dojo.connect(selectionToolbar, "onDrawEnd", findPointsInExtent);

      }

      function showResults(results) {

          var len = results.features.length;
          var featureSet = new FeatureSet();
          featureSet = results;

         graphicsLayer = new esri.layers.GraphicsLayer();
          //graphicsLayer.setInfoTemplate(new esri.InfoTemplate("Attributes", "${*}"));
           
          dojo.forEach(featureSet.features, function (feature,index) {
             
              var spID = featureSet.features[index].attributes.SP_ID;
              var address = featureSet.features[index].attributes.ADDRESS;
              var callbackstatus = featureSet.features[index].attributes.CALLBACKSTATUS;
              var meterNumber = featureSet.features[index].attributes.METERNUMBER;

              feature.geometry = new esri.geometry.Point(featureSet.features[index].attributes.GIS_X, featureSet.features[index].attributes.GIS_Y, new esri.SpatialReference({ wkid: 4326 }));
              //graphic = new esri.Graphic(feature, simpleMarkerSymbol);
              feature.symbol = simpleMarkerSymbol;
             graphicsLayer.add(feature);

          });
          mapMain.addLayer(graphicsLayer);      
      }

      function findPointsInExtent(extent) {

         var graphics = mapMain.graphics.graphics;
          var results = [];
          //dojo.forEach(mapMain.graphics.graphics, function (graphic) {
          for (var i = 0, il = graphics.length; i < il; i++) {
              graphic = graphics;
              if (extent.contains(graphic.geometry)) {
                  graphic.setSymbol(highlightSymbol);
                  //selectionLayer.add(graphic);
                  results.push(graphic.getContent());
                  //Grab Results here and push to slide out or form - look at Washington State city selection example
                  //results.push(graphic.getContent());
              }
                  //else if point was previously highlighted, reset its symbology
              else if (graphic.symbol == highlightSymbol) {
                  graphic.setSymbol(simpleMarkerSymbol);
              }

          };
          selectionToolbar.deactivate();
      }

      function errBack(results) {
          alert(results);

      }

  });




---------------------------------------------------
HTML PAGE
---------------------------------------------------

<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title>CP-Isolated Steel Services</title>

    <!-- Configure dojo for asynchronous module loading -->
    <script>
        var dojoConfig = {
            async: true
        };
    </script>

    <!-- Reference libraries. The first CSS is a Dojo theme that gives dijits a consistent style. -->
    <link rel="stylesheet" href="http://js.arcgis.com/3.7/js/dojo/dijit/themes/nihilo/nihilo.css">
    <link rel="stylesheet" href="http://js.arcgis.com/3.7/js/esri/css/esri.css">
    <link rel="stylesheet" href="css/workwiththemap.css"/>
    <script src="http://js.arcgis.com/3.7/"></script>
    <script src="JavaScript/CP_IsolatedSteelServices.js"></script>
  </head>
  <body class="nihilo">
     <button data-dojo-type="dijit.form.Button" onClick="selectionToolbar.activate(esri.toolbars.Draw.EXTENT);">Select</button>
     <button data-dojo-type="dijit.form.Button" onClick="graphic.setSymbol(highlightSymbol);">Clear Selection</button><br>
     
      <div id="cpCenter" data-dojo-type="dijit/layout/BorderContainer" data-dojo-props="design:'sidebar', liveSplitters:'true'" >
    </div>
  </body>
</html>
0 Kudos
1 Solution

Accepted Solutions
JakeSkinner
Esri Esteemed Contributor
Since you are not using the map's default graphic layer, update the  findPointsInExtent function to use the GraphicsLayer you created.  Try the following below:

function showResults(results) {                  var len = results.features.length;        var featureSet = new FeatureSet();        featureSet = results;                graphicsLayer = new esri.layers.GraphicsLayer();                 dojo.forEach(featureSet.features, function (feature,index) {                    var spID = featureSet.features[index].attributes.SP_ID;           var address = featureSet.features[index].attributes.ADDRESS;           var callbackstatus = featureSet.features[index].attributes.CALLBACKSTATUS;           var meterNumber = featureSet.features[index].attributes.METERNUMBER;                    feature.geometry = new esri.geometry.Point(featureSet.features[index].attributes.GIS_X, featureSet.features[index].attributes.GIS_Y, new esri.SpatialReference({ wkid: 4326 }));           feature.symbol = defaultSymbol;           graphicsLayer.add(feature);                  });         mapMain.addLayer(graphicsLayer);  }  function findPointsInExtent(extent) {     var graphics = graphicsLayer;      dojo.forEach(graphics.graphics, function (graphic) {                 for (var i = 0, il = graphics.graphics.length; i < il; i++) {                     if (extent.contains(graphic.geometry)) {                 graphic.setSymbol(highlightSymbol);                                  }                 else if (graphic.symbol == highlightSymbol) {             graphic.setSymbol(defaultSymbol);             }         }      })   }

View solution in original post

0 Kudos
4 Replies
JakeSkinner
Esri Esteemed Contributor
Hi Brandon,

Each map contains a graphics layer by default, so you won't have to create one.  The graphics layer is accessible using the Map.Graphics property.

Try the following:

/// <reference path="index.html" />
var mapMain, selectionLayer, graphicsLayer, selectionToolbar, graphic, defaultSymbol, highlightSymbol, resultTemplate;

require([
    "esri/map",
    "esri/geometry/Extent",
    "esri/layers/ArcGISTiledMapServiceLayer",
    "esri/layers/FeatureLayer",
    "esri/tasks/GeometryService",
    "esri/tasks/query",
    "esri/tasks/QueryTask",
    "esri/tasks/FeatureSet",
    "esri/graphic",
    "esri/toolbars/draw",
    "esri/config",
    
    "dojo/ready",
    "dojo/parser",
    "dojo/on",
    "dojo/dom",
    "dojo/_base/array",
    
    "dijit/layout/BorderContainer",
    "dijit/layout/ContentPane"],
function (
    Map, Extent, ArcGISTiledMapServiceLayer, FeatureLayer,
    GeometryService, Query, QueryTask, FeatureSet, graphic, draw, config,
    ready, parser, on, dom, array, BorderContainer, ContentPane
) {

ready(function () {

    // Create the map
    mapMain = new Map("cpCenter")
    var layerURL = "http://gisaprd/ArcGIS/rest/services/BaseMap_ArcReader_Cached/MapServer";
    myLayer = new esri.layers.ArcGISTiledMapServiceLayer(layerURL);
    mapMain.addLayer(myLayer);
    
    dojo.connect(mapMain, "onLoad", initSelectToolbar);
    
    button2 = dom.byId("clearButton");
    on(button2, "click", clearSelection);
    
    var queryTask = new QueryTask("http://gisaprd/ArcGIS/rest/services/SRSOutageTest/MapServer/3");
    
    var query = new Query();
    query.returnGeometry = true;
    query.outFields = ["*"];
    query.where = "GIS_X IS NOT NULL";
    queryTask.execute(query, showResults, errBack);        
        
    defaultSymbol = new esri.symbol.SimpleMarkerSymbol().setColor(new dojo.Color([0, 0, 255]));
    highlightSymbol = new esri.symbol.SimpleMarkerSymbol().setColor(new dojo.Color([255, 0, 0]));
    });

function initSelectToolbar(mapMain) {
    selectionToolbar = new esri.toolbars.Draw(mapMain);
    
    dojo.connect(selectionToolbar, "onDrawEnd", findPointsInExtent);

}

function showResults(featureSet) {  
   dojo.forEach(featureSet.features,function(feature){
          mapMain.graphics.add(feature.setSymbol(defaultSymbol));
        });

}

function findPointsInExtent(extent) {
    var results = [];
    dojo.forEach(mapMain.graphics.graphics,function(graphic){
      if (extent.contains(graphic.geometry)) {
        graphic.setSymbol(highlightSymbol);            
      }      
      else if (graphic.symbol == highlightSymbol) {
        graphic.setSymbol(defaultSymbol);
      }
    });   
}


function errBack(results) {
    alert(results);
}

function clearSelection(){
    selectionToolbar.deactivate();
    dojo.forEach(mapMain.graphics.graphics,function(graphic){    
        graphic.setSymbol(defaultSymbol); 
    });                 
}

});


I also added a function to clear the selection.  You can call the button from your HTML using the 'dojo/dom' module, and then execute the 'clearSelection' function:

button2 = dom.byId("clearButton");
on(button2, "click", clearSelection);


Here is the updated HTML:

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>CP-Isolated Steel Services</title>

<!-- Configure dojo for asynchronous module loading -->
<script>
var dojoConfig = {
async: true
};
</script>

<!-- Reference libraries. The first CSS is a Dojo theme that gives dijits a consistent style. -->
<link rel="stylesheet" href="http://js.arcgis.com/3.7/js/dojo/dijit/themes/nihilo/nihilo.css">
<link rel="stylesheet" href="http://js.arcgis.com/3.7/js/esri/css/esri.css">
<link rel="stylesheet" href="css/workwiththemap.css"/>
<script src="http://js.arcgis.com/3.7/"></script>
<script src="JavaScript/CP_IsolatedSteelServices.js"></script>
</head>
<body class="nihilo">
<button data-dojo-type="dijit.form.Button" id="selectButton" onClick="selectionToolbar.activate(esri.toolbars.Draw.EXTENT);">Select</button>
<button data-dojo-type="dijit.form.Button" id="clearButton">Clear Selection</button><br>

<div id="cpCenter" data-dojo-type="dijit/layout/BorderContainer" data-dojo-props="design:'sidebar', liveSplitters:'true'" >
</div>
</body>
</html> 
0 Kudos
BrandonIves
New Contributor
Jake,

Thanks for the reply. I am still curious how to select graphics within a graphics layer because I know I will possibly be adding multiple points features from different sources that I would like to control from a legend or toggle menu to turn the layers off and on. Ex: Items that need inspected this year, next year, etc. I also need to select the individual layers to assign work and complete work.

I will be getting all of my data from an Oracle table without a spatial component so I won't be able to return any geometry because there isn't any. I will have x/y fields to let me plot the point.

Coming from a silverlight background I know I had to create multiple graphics layers, one for each layer. Is there a way to select individual graphics within the graphics layer?

Thanks!
0 Kudos
JakeSkinner
Esri Esteemed Contributor
Since you are not using the map's default graphic layer, update the  findPointsInExtent function to use the GraphicsLayer you created.  Try the following below:

function showResults(results) {                  var len = results.features.length;        var featureSet = new FeatureSet();        featureSet = results;                graphicsLayer = new esri.layers.GraphicsLayer();                 dojo.forEach(featureSet.features, function (feature,index) {                    var spID = featureSet.features[index].attributes.SP_ID;           var address = featureSet.features[index].attributes.ADDRESS;           var callbackstatus = featureSet.features[index].attributes.CALLBACKSTATUS;           var meterNumber = featureSet.features[index].attributes.METERNUMBER;                    feature.geometry = new esri.geometry.Point(featureSet.features[index].attributes.GIS_X, featureSet.features[index].attributes.GIS_Y, new esri.SpatialReference({ wkid: 4326 }));           feature.symbol = defaultSymbol;           graphicsLayer.add(feature);                  });         mapMain.addLayer(graphicsLayer);  }  function findPointsInExtent(extent) {     var graphics = graphicsLayer;      dojo.forEach(graphics.graphics, function (graphic) {                 for (var i = 0, il = graphics.graphics.length; i < il; i++) {                     if (extent.contains(graphic.geometry)) {                 graphic.setSymbol(highlightSymbol);                                  }                 else if (graphic.symbol == highlightSymbol) {             graphic.setSymbol(defaultSymbol);             }         }      })   }
0 Kudos
BrandonIves
New Contributor
Jake,

Awesome suggestion. I was assuming I would have to search the values by explicitly saying what graphics layer to get to its graphics features. EX: mapMain.graphicsLayer.graphics

I can throw a break point into the for loop and watch it iterate through whether the graphic is in the extent or not but the web page hangs up and never finishes the function. I am trying to trouble shoot that now.
0 Kudos