JSAPI v4.3 - IdentifyTask returns feature even if layer is not visible

3393
15
03-30-2017 05:43 AM
MaximeDemers
Occasional Contributor III

Hi!

Is it normal that the IdentifyTask returns features even if the layer is not visible? I see in the documentation that the layerOption parameter in the IdentifyParameters should define if the IdentifyTask will return feature for visibile layer only. However, this parameter seem not working. The popup is displayed even if the layer is not visible as shown below. The image and code below are taken from the documentation sample codes

 <script>
    require([
      "esri/Map",
      "esri/views/MapView",
      "esri/layers/TileLayer",
      "esri/tasks/IdentifyTask",
      "esri/tasks/support/IdentifyParameters",
      "dojo/_base/array",
      "dojo/on",
      "dojo/dom",
      "dojo/domReady!"
    ], function(
      Map, MapView, TileLayer,
      IdentifyTask, IdentifyParameters,
      arrayUtils, on, dom
    ) {

      var identifyTask, params;

      // URL to the map service where the identify will be performed
      var soilURL =
        "https://services.arcgisonline.com/arcgis/rest/services/Specialty/Soil_Survey_Map/MapServer";

      // Add the map service as a TileLayer for fast rendering
      // Tile layers are composed of non-interactive images. For that reason we'll
      // use IdentifyTask to query the service to add interactivity to the app
      var parcelsLyr = new TileLayer({
        url: soilURL,
        opacity: 0.85,
        visible: false
      });

      var map = new Map({
        basemap: "osm"
      });
      map.add(parcelsLyr);

      var view = new MapView({
        map: map,
        container: "viewDiv",
        center: [-120.174, 47.255],
        zoom: 7
      });

      view.then(function() {
        // executeIdentifyTask() is called each time the view is clicked
        on(view, "click", executeIdentifyTask);

        // Create identify task for the specified map service
        identifyTask = new IdentifyTask(soilURL);

        // Set the parameters for the Identify
        params = new IdentifyParameters();
        params.tolerance = 3;
        params.layerIds = [0, 1, 2];
        params.layerOption = "top";
        params.width = view.width;
        params.height = view.height;
      });

      // Executes each time the view is clicked
      function executeIdentifyTask(event) {
        // Set the geometry to the location of the view click
        params.geometry = event.mapPoint;
        params.mapExtent = view.extent;
        dom.byId("viewDiv").style.cursor = "wait";

        // This function returns a promise that resolves to an array of features
        // A custom popupTemplate is set for each feature based on the layer it
        // originates from
        identifyTask.execute(params).then(function(response) {

          var results = response.results;

          return arrayUtils.map(results, function(result) {

            var feature = result.feature;
            var layerName = result.layerName;

            feature.attributes.layerName = layerName;
            if (layerName === 'Soil Survey Geographic') {
              feature.popupTemplate = { // autocasts as new PopupTemplate()
                title: "{Map Unit Name}",
                content: "<b>Dominant order:</b> {Dominant Order} ({Dom. Cond. Order %}%)" +
                  "<br><b>Dominant sub-order:</b> {Dominant Sub-Order} ({Dom. Cond. Suborder %}%)" +
                  "<br><b>Dominant Drainage Class:</b> {Dom. Cond. Drainage Class} ({Dom. Cond. Drainage Class %}%)" +
                  "<br><b>Farmland Class:</b> {Farmland Class}"
              };
            }
            else if (layerName === 'State Soil Geographic') {
              feature.popupTemplate = { // autocasts as new PopupTemplate()
                title: "{Map Unit Name}",
                content: "<b>Dominant order:</b> {Dominant Order} ({Dominant %}%)" +
                  "<br><b>Dominant sub-order:</b> {Dominant Sub-Order} ({Dominant Sub-Order %}%)"
              };
            }
            else if (layerName === 'Global Soil Regions') {
              feature.popupTemplate = { // autocasts as new PopupTemplate()
                title: layerName,
                content: "<b>Dominant order:</b> {Dominant Order}" +
                  "<br><b>Dominant sub-order:</b> {Dominant Sub-Order}"
              };
            }
            return feature;
          });
        }).then(showPopup); // Send the array of features to showPopup()

        // Shows the results of the Identify in a popup once the promise is resolved
        function showPopup(response) {
          if (response.length > 0) {
            view.popup.open({
              features: response,
              location: event.mapPoint
            });
          }
          dom.byId("viewDiv").style.cursor = "auto";
        }
      }
    });
  </script>‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
0 Kudos
15 Replies
ThomasSolow
Occasional Contributor III

By default it looks like identify is run on the top layer only, regardless of client layer visibility.  You can change this using the identify params.  For instance if you wanted to run identify only on visible layers, you could set the "layerOption" property on the params to "visible."

IdentifyParameters | API Reference | ArcGIS API for JavaScript 4.3

If you want to get specific about which layers to query, you can pass an array of layerIds in as the "layerIds" property.

0 Kudos
MaximeDemers
Occasional Contributor III

Thats not what the doc says about the layerOption "top" paramerer: Only the top-most VISIBLE layer is identified.

Anyway setting the layerOption to "visible" does not make any difference. You can try directly in the sample code sandbox

0 Kudos
KenBuja
MVP Esteemed Contributor

What you'll have to do is set the layerIds property to -1 (setting it to "[]" doesn't work, like it did in 3.x)

params = new IdentifyParameters();
params.tolerance = 3;
params.layerIds = [-1];
params.layerOption = "top";
params.width = view.width;
params.height = view.height;‍‍‍‍‍‍
0 Kudos
MaximeDemers
Occasional Contributor III

Doing that, it wont work when the layer is visible...

0 Kudos
KenBuja
MVP Esteemed Contributor

So what you'll have to do is put a little code in to determine whether the layer is visible

if (parcelsLyr.visible) {
  params.layerIds = [0,1,2];
} else {
  params.layerIds = [-1];
}
0 Kudos
MaximeDemers
Occasional Contributor III

Imagine you have more than one layer that you want to use with the IdentifyTask, for instance subLayers in a MapImageLayer, you wont be able to use such workaround.

It seems to be a bug in the API right?

0 Kudos
KenBuja
MVP Esteemed Contributor

Yes, it does seem to be a bug. However, I'm not sure why you couldn't simply determine which layers are visible and use that in the layerIds property. For example, in the sandbox example, if I use

params.layerIds = [1];

then I get the result at the initial zoom level, but not when I zoom in or out far enough where the visible map changes from "State Soil Geographic" to "Soil Survey Geographic" or "Global Soil Regions"

0 Kudos
ThomasSolow
Occasional Contributor III

I'd consider it a bug since "visible" doesn't appear to be working, and the documentation for "top" appears to be wrong.

It's not clear to me what a layer id is in this situation.  You should be able to use Collection.flatten to get all layers + all sublayers and then map that to a list of ids.  But what does [0,1,2] refer to here?  Are those ids just "index of layer?"

0 Kudos
MaximeDemers
Occasional Contributor III

According to me, the layerIds property refer to the subLayers ids (see for instance MapImageLayer.subLayers in the documentation.) When you instantiate an IdentifyTask(), you give the url  of the layer that would be queried by the tool. So, layerIds is not related to every layers in the map, only the subLayers of the layer you have initiate the IdentifyTask with.

How is possible that no one have ever encountered this bug before? I can't believe it. I think it would be trivial to fix it, but how long shall we wait for the fix?

0 Kudos