odoe

Quick Tip - What did I click on?

Blog Post created by odoe on Oct 7, 2015

mappins.jpg

Photo: pin points | Flickr - Photo Sharing!

 

So I've seen this come up a couple of times. You have some FeatureLayers on your map.

 

You set up a listener for clicks on the map.

 

You click on the map.

 

You have maybe six layers, but you only get back one graphic.

 

What's up with that?

 

Ok, so yeah, this just has to do with what layers are where. Graphics on you map probably SVG. It just so happens that if an SVG has no fill, you can't get a click event from it. You can however set the opacity to clear and still get a click event, so keep that in mind.

 

But it's also a web thing. The way SVG graphics work (all DOM elements really), the click event just comes up from the top element. It doesn't click through to other elements.

 

So you're screwed right?

 

Not so fast.

 

You have a couple of options here. The first is to use a QueryTask. You can simply query all the layers and get results for features at the location you clicked. This is a nice clean solution and works great for polygons. Points and Lines are a little trickier. If you don't click exactly where the point or line is, you won't get a result. So you could make a little buffer of the location you clicked on using the GeometryEngine if you like to try and get a better result. I'll leave that up to you.

 

You can also use the IdentifyTask. This takes a little more work to set up when using FeatureLayers and experimenting with a tolerance, which is similar to the buffer we talked about earlier.

 

I personally think the QueryTask with a buffered geometry is a better solution, but at least you have some options.

 

Here's what this might look like:

 

require([
  "esri/map",
  "esri/layers/FeatureLayer",
  "esri/tasks/query",
  "esri/tasks/IdentifyTask",
  "esri/tasks/IdentifyParameters",
  "dojo/promise/all",
  "dojo/domReady!"
], function(Map, FeatureLayer, Query, IdTask, IdParams, all) { 
  var map = new Map("mapDiv", {
    center: [-118.182, 33.913],
    zoom: 14,
    basemap: "topo"
  });
  
  var layer0 = new FeatureLayer("http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Demographics/ESRI_Census_USA/MapServer/0");
  
  var layer1 = new FeatureLayer("http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Demographics/ESRI_Census_USA/MapServer/1");
  
  map.addLayers([layer0, layer1]);
  
  // conventional method
  map.on('click', function(e) {
    // only one graphic 
    console.log(e.graphic);
    // let's get freaky *_*
    var q = new Query();
    q.returnGeometry = true;
    q.outFields = ["*"];
    q.geometry = e.mapPoint;
    // distance and units are for Hosted Feature Services Only 
    q.units = "feet";
    q.distance = 50;
    // Query all the FeautreLayers
    var defs = [layer0, layer1].map(function(x) {
      return x.queryFeatures(q);
    });
    all(defs).then(function(results) {
      console.log("all query results", results);
    });
    
    // Or use IdentifyTask, super freaky! #_#
    var idParams = new IdParams();
    idParams.geometry = e.mapPoint;
    idParams.mapExtent = map.extent;
    // You'll need to experiment with tolerance
    // to get the desired results
    idParams.tolerance = 10;
    idParams.layerOption = IdParams.LAYER_OPTION_ALL;
    var url = layer0.url.substr(0, layer0.url.lastIndexOf("/"));
    idParams.layerIds = [layer0, layer1].map(function(x) {
      return x.url.substr(x.url.lastIndexOf("/") + 1, x.length);
    });
    console.log(idParams);
    var idTask = new IdTask(url);
    idTask.execute(idParams).then(function(results) {
      console.log("id results", results);
    });
  });
  
});

 

You can find a live demo here.

 

So  don't let little limitations get you down. You can get just about anything done with a little elbow grease.

 

For more geodev tips and tricks, check out my blog.

Outcomes