multiple ArcGISDynamicMapServiceLayer IdentifyTask

10470
12
Jump to solution
06-04-2014 04:53 PM
ArowanaIndah
New Contributor III
Hi,
I'm using 'Display identify results in popup' sample and try to add 2 or 3 ArcGISDynamicMapServiceLayer. How do i configure the code so that the popup will show result of selected ArcGISDynamicMapServiceLayer.

Thank

<!DOCTYPE html>  <html>     <head>      <meta http-equiv="Content-Type" content="text/html; charset=utf-8">      <!--The viewport meta tag is used to improve the presentation and behavior of the samples         on iOS devices-->      <meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no">      <title>Identify with Popup</title>        <link rel="stylesheet" href="http://js.arcgis.com/3.9/js/esri/css/esri.css">      <style>        html, body, #map {          height:100%;          width:100%;          margin:0;          padding:0;        }      </style>        <script src="http://js.arcgis.com/3.9/"></script>      <script>        var map;          require([          "esri/map",          "esri/InfoTemplate",          "esri/layers/ArcGISDynamicMapServiceLayer",          "esri/symbols/SimpleFillSymbol",          "esri/symbols/SimpleLineSymbol",          "esri/tasks/IdentifyTask",          "esri/tasks/IdentifyParameters",          "esri/dijit/Popup",          "dojo/_base/array",          "esri/Color",          "dojo/dom-construct",          "dojo/domReady!"        ], function (          Map, InfoTemplate, ArcGISDynamicMapServiceLayer, SimpleFillSymbol,          SimpleLineSymbol, IdentifyTask, IdentifyParameters, Popup,          arrayUtils, Color, domConstruct        ) {            var identifyTask, identifyParams;            var popup = new Popup({            fillSymbol: new SimpleFillSymbol(SimpleFillSymbol.STYLE_SOLID,              new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID,                new Color([255, 0, 0]), 2), new Color([255, 255, 0, 0.25]))          }, domConstruct.create("div"));            map = new Map("map", {            basemap: "satellite",            center: [-83.275, 42.573],            zoom: 18,            infoWindow: popup          });            map.on("load", mapReady);            var parcelsURL = "http://sampleserver3.arcgisonline.com/ArcGIS/rest/services/BloomfieldHillsMichigan/Parcels/MapServer";          map.addLayer(new ArcGISDynamicMapServiceLayer(parcelsURL,            { opacity: .55 }));            function mapReady () {            map.on("click", executeIdentifyTask);            //create identify tasks and setup parameters            identifyTask = new IdentifyTask(parcelsURL);              identifyParams = new IdentifyParameters();            identifyParams.tolerance = 3;            identifyParams.returnGeometry = true;            identifyParams.layerIds = [0, 2];            identifyParams.layerOption = IdentifyParameters.LAYER_OPTION_ALL;            identifyParams.width = map.width;            identifyParams.height = map.height;          }            function executeIdentifyTask (event) {            identifyParams.geometry = event.mapPoint;            identifyParams.mapExtent = map.extent;              var deferred = identifyTask              .execute(identifyParams)              .addCallback(function (response) {                // response is an array of identify result objects                // Let's return an array of features.                return arrayUtils.map(response, function (result) {                  var feature = result.feature;                  var layerName = result.layerName;                    feature.attributes.layerName = layerName;                  if (layerName === 'Tax Parcels') {                    var taxParcelTemplate = new InfoTemplate("",                      "${Postal Address} <br/> Owner of record: ${First Owner Name}");                    feature.setInfoTemplate(taxParcelTemplate);                  }                  else if (layerName === 'Building Footprints') {                    console.log(feature.attributes.PARCELID);                    var buildingFootprintTemplate = new InfoTemplate("",                      "Parcel ID: ${PARCELID}");                    feature.setInfoTemplate(buildingFootprintTemplate);                  }                  return feature;                });              });              // InfoWindow expects an array of features from each deferred            // object that you pass. If the response from the task execution            // above is not an array of features, then you need to add a callback            // like the one above to post-process the response and return an            // array of features.            map.infoWindow.setFeatures([deferred]);            map.infoWindow.show(event.mapPoint);          }        });      </script>    </head>        <body>      <div id="map"></div>    </body>    </html>
0 Kudos
1 Solution

Accepted Solutions
KenBuja
MVP Esteemed Contributor

Here is an example of having multiple dynamic services. This also adds in attributes showing which service each result comes from.

<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <!--The viewport meta tag is used to improve the presentation and behavior of the samples
      on iOS devices-->
    <meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no">
    <title>Identify with Popup</title>

    <link rel="stylesheet" href="http://js.arcgis.com/3.8/js/esri/css/esri.css">
    <style>
        html, body, #map {
            height: 100%;
            width: 100%;
            margin: 0;
            padding: 0;
        }
    </style>

    <script>var dojoConfig = { parseOnLoad: true };</script>
    <script src="http://js.arcgis.com/3.8/"></script>
    <script>

        var map;
        var identifyTask, identifyParams, idPoint;
        var identifyResults;

        require([
          "esri/map", "esri/dijit/Popup", "dojo/promise/all", "dojo/domReady!"
        ], function (
          Map, Popup, All
        ) {
            var popup = new Popup({
                fillSymbol: new esri.symbol.SimpleFillSymbol(esri.symbol.SimpleFillSymbol.STYLE_SOLID, new esri.symbol.SimpleLineSymbol(esri.symbol.SimpleLineSymbol.STYLE_SOLID, new dojo.Color([255, 0, 0]), 2), new dojo.Color([255, 255, 0, 0.25]))
            }, dojo.create("div"));

            map = new Map("map", {
                basemap: "satellite",
                center: [-83.275, 42.573],
                zoom: 18,
                infoWindow: popup
            });

            dojo.connect(map, "onLoad", mapReady);

            var landBaseLayer = new esri.layers.ArcGISDynamicMapServiceLayer("http://sampleserver3.arcgisonline.com/ArcGIS/rest/services/BloomfieldHillsMichigan/Parcels/MapServer", { opacity: .55 });
            map.addLayer(landBaseLayer);

            var militaryLayer = new esri.layers.ArcGISDynamicMapServiceLayer("http://sampleserver6.arcgisonline.com/arcgis/rest/services/Military/MapServer", { opacity: .55 });
            map.addLayer(militaryLayer);
            console.log(militaryLayer.declaredClass);


            function mapReady(map) {
                dojo.connect(map, "onClick", runIdentifies);
            }

            function runIdentifies(evt) {
                identifyResults = [];
                idPoint = evt.mapPoint;
                var layers = dojo.map(map.layerIds, function (layerId) {
                    return map.getLayer(layerId);
                });
                layers = dojo.filter(layers, function (layer) {
                    if (layer.visibleLayers[0] !== -1) {
                        return layer.getImageUrl && layer.visible
                    }
                }); //Only dynamic layers have the getImageUrl function. Filter so you only query visible dynamic layers
                var tasks = dojo.map(layers, function (layer) {
                    return new esri.tasks.IdentifyTask(layer.url);
                }); //map each visible dynamic layer to a new identify task, using the layer url
                var defTasks = dojo.map(tasks, function (task) {
                    return new dojo.Deferred();
                }); //map each identify task to a new dojo.Deferred
                var params = createIdentifyParams(layers, evt);

                var promises = [];

                for (i = 0; i < tasks.length; i++) {
                    promises.push(tasks.execute(params)); //Execute each task
                }

                var allPromises = new All(promises);
                allPromises.then(function (r) { showIdentifyResults(r, tasks); });
            }

            function showIdentifyResults(r, tasks) {
                var results = [];
                var taskUrls = [];
                r = dojo.filter(r, function (result) {
                    return r[0];
                });
                for (i = 0; i < r.length; i++) {
                    results = results.concat(r);
                    for (j = 0; j < r.length; j++) {
                        taskUrls = taskUrls.concat(tasks.url);
                    }
                }
                results = dojo.map(results, function (result, index) {
                    var feature = result.feature;
                    var layerName = result.layerName;
                    var serviceUrl = taskUrls[index];
                    feature.attributes.layerName = result.layerName;

                    var template = new esri.InfoTemplate("", "Service Url: " + serviceUrl + "<br/><br/>Layer name: " + result.layerName + "<br/><br/> Object Id: ${OBJECTID}");
                    feature.setInfoTemplate(template);

                    var resultGeometry = feature.geometry;
                    var resultType = resultGeometry.type;
                    return feature;
                });

                if (results.length === 0) {
                    map.infoWindow.clearFeatures();
                } else {
                    map.infoWindow.setFeatures(results);
                }
                map.infoWindow.show(idPoint);
                return results;
            }

            function createIdentifyParams(layers, evt) {
                var identifyParamsList = [];
                identifyParamsList.length = 0;
                dojo.forEach(layers, function (layer) {
                    var idParams = new esri.tasks.IdentifyParameters();
                    idParams.width = map.width;
                    idParams.height = map.height;
                    idParams.geometry = evt.mapPoint;
                    idParams.mapExtent = map.extent;
                    idParams.layerOption = esri.tasks.IdentifyParameters.LAYER_OPTION_VISIBLE;
                    var visLayers = layer.visibleLayers;
                    if (visLayers !== -1) {
                        var subLayers = [];
                        for (var i = 0; i < layer.layerInfos.length; i++) {
                            if (layer.layerInfos.subLayerIds == null)
                                subLayers.push(layer.layerInfos.id);
                        }
                        idParams.layerIds = subLayers;
                    } else {
                        idParams.layerIds = [];
                    }
                    idParams.tolerance = 3;
                    idParams.returnGeometry = true;
                    identifyParamsList.push(idParams);
                });
                return identifyParamsList;
            }

        });
    </script>
</head>

<body>
    <div id="map"></div>
</body>

</html>

View solution in original post

12 Replies
KenBuja
MVP Esteemed Contributor
You'll have to run the IdentifyTask on each of the layers that you've added. Take a look at this thread to see how to do it. Also, you can look at this example (but it was written in legacy style)
ArowanaIndah
New Contributor III
Hi,
Thank for reply. I'm being using this code and it's work for two ArcGISDynamicMapServiceLayer. I try to work with third ArcGISDynamicMapServiceLayer and get stuck with coding and i'm not very good in coding.

Thank for help.

     dojo.connect(map,"onClick",executeIdentifyTask);
       
       //create identify tasks and setup parameters 
       identifyTaskCombined = new esri.tasks.IdentifyTask("<//URL Services>");
       identifyTaskReps = new esri.tasks.IdentifyTask("<//URL Services>");
       identifyTaskZoning = new esri.tasks.IdentifyTask("<//URL Services>");
        
       identifyParamsCombined = new esri.tasks.IdentifyParameters();
       identifyParamsCombined.tolerance = 7;
       identifyParamsCombined.returnGeometry = true;
       identifyParamsCombined.layerIds = [2];
       identifyParamsCombined.layerOption = esri.tasks.IdentifyParameters.LAYER_OPTION_VISIBLE;
       identifyParamsCombined.width  = map.width;
       identifyParamsCombined.height = map.height;
    
       identifyParamsReps = new esri.tasks.IdentifyParameters();
       identifyParamsReps.tolerance = 7;
       identifyParamsReps.returnGeometry = true;
       identifyParamsReps.layerIds = [2];
       identifyParamsReps.layerOption = esri.tasks.IdentifyParameters.LAYER_OPTION_VISIBLE;
       identifyParamsReps.width  = map.width;
       identifyParamsReps.height = map.height;
    
       identifyParamsZoning = new esri.tasks.IdentifyParameters();
       identifyParamsZoning.tolerance = 7;
       identifyParamsZoning.returnGeometry = true;
       identifyParamsZoning.layerIds = [2];
       identifyParamsZoning.layerOption = esri.tasks.IdentifyParameters.LAYER_OPTION_VISIBLE;
       identifyParamsZoning.width  = map.width;
       identifyParamsZoning.height = map.height;

       
       //resize the map when the browser resizes
       dojo.connect(dijit.byId('map'), 'resize', map,map.resize);
      };

   function executeIdentifyTask(evt){
     identifyParamsReps.geometry = evt.mapPoint;
     identifyParamsReps.mapExtent = map.extent;
     var deferred = identifyTaskReps.execute(identifyParamsReps);
     deferred.addCallback(function(response){
       if (response.length > 0) {
//         console.log(response.length)
//         response is an array of identify result objects    
//         Let's return an array of features.
        return dojo.map(response, function(result){
          var feature = result.feature;
          feature.attributes.layerName = result.layerName;
          var template = new esri.InfoTemplate("", "");
          feature.setInfoTemplate(template);
        return feature;
        });
        }
      else {
          identifyParamsCombined.geometry = evt.mapPoint;
          identifyParamsCombined.mapExtent = map.extent;
          var deferred = identifyTaskCombined.execute(identifyParamsCombined);
          deferred.addCallback(function(response){
            // response is an array of identify result objects    
            // Let's return an array of features.
            return dojo.map(response, function(result){
              var feature = result.feature;
              feature.attributes.layerName = result.layerName;
                  var template = new esri.InfoTemplate("", ""); //booger
                  feature.setInfoTemplate(template);
            return feature;
            });
          });
      };
        map.infoWindow.setFeatures([deferred]);
        map.infoWindow.show(evt.mapPoint);          
      });
        map.infoWindow.setFeatures([deferred]);
        map.infoWindow.show(evt.mapPoint);      
      };
0 Kudos
ArowanaIndah
New Contributor III
Hi,
I really appreciate any help.

Thank
0 Kudos
OwenEarley
Occasional Contributor III
If you have access to the ArcGIS Server I would suggest placing all 3 layers into a single map service and then configure the IdentifyParameters to use the layers that you are interested in.

identifyTask = new IdentifyTask("http://server/ArcGIS/rest/services/YourNewCombinedLayers/MapServer");
identifyParams = new IdentifyParameters();
...
identifyParams.layerIds = [0, 1, 2]; //Layer ids in the new map service
...


If you don't have access to create new map services then you may need to look into Dojo deferred lists:
http://dojotoolkit.org/reference-guide/1.9/dojo/DeferredList.html

Owen
www.spatialxp.com.au
0 Kudos
KenBuja
MVP Esteemed Contributor

Here is an example of having multiple dynamic services. This also adds in attributes showing which service each result comes from.

<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <!--The viewport meta tag is used to improve the presentation and behavior of the samples
      on iOS devices-->
    <meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no">
    <title>Identify with Popup</title>

    <link rel="stylesheet" href="http://js.arcgis.com/3.8/js/esri/css/esri.css">
    <style>
        html, body, #map {
            height: 100%;
            width: 100%;
            margin: 0;
            padding: 0;
        }
    </style>

    <script>var dojoConfig = { parseOnLoad: true };</script>
    <script src="http://js.arcgis.com/3.8/"></script>
    <script>

        var map;
        var identifyTask, identifyParams, idPoint;
        var identifyResults;

        require([
          "esri/map", "esri/dijit/Popup", "dojo/promise/all", "dojo/domReady!"
        ], function (
          Map, Popup, All
        ) {
            var popup = new Popup({
                fillSymbol: new esri.symbol.SimpleFillSymbol(esri.symbol.SimpleFillSymbol.STYLE_SOLID, new esri.symbol.SimpleLineSymbol(esri.symbol.SimpleLineSymbol.STYLE_SOLID, new dojo.Color([255, 0, 0]), 2), new dojo.Color([255, 255, 0, 0.25]))
            }, dojo.create("div"));

            map = new Map("map", {
                basemap: "satellite",
                center: [-83.275, 42.573],
                zoom: 18,
                infoWindow: popup
            });

            dojo.connect(map, "onLoad", mapReady);

            var landBaseLayer = new esri.layers.ArcGISDynamicMapServiceLayer("http://sampleserver3.arcgisonline.com/ArcGIS/rest/services/BloomfieldHillsMichigan/Parcels/MapServer", { opacity: .55 });
            map.addLayer(landBaseLayer);

            var militaryLayer = new esri.layers.ArcGISDynamicMapServiceLayer("http://sampleserver6.arcgisonline.com/arcgis/rest/services/Military/MapServer", { opacity: .55 });
            map.addLayer(militaryLayer);
            console.log(militaryLayer.declaredClass);


            function mapReady(map) {
                dojo.connect(map, "onClick", runIdentifies);
            }

            function runIdentifies(evt) {
                identifyResults = [];
                idPoint = evt.mapPoint;
                var layers = dojo.map(map.layerIds, function (layerId) {
                    return map.getLayer(layerId);
                });
                layers = dojo.filter(layers, function (layer) {
                    if (layer.visibleLayers[0] !== -1) {
                        return layer.getImageUrl && layer.visible
                    }
                }); //Only dynamic layers have the getImageUrl function. Filter so you only query visible dynamic layers
                var tasks = dojo.map(layers, function (layer) {
                    return new esri.tasks.IdentifyTask(layer.url);
                }); //map each visible dynamic layer to a new identify task, using the layer url
                var defTasks = dojo.map(tasks, function (task) {
                    return new dojo.Deferred();
                }); //map each identify task to a new dojo.Deferred
                var params = createIdentifyParams(layers, evt);

                var promises = [];

                for (i = 0; i < tasks.length; i++) {
                    promises.push(tasks.execute(params)); //Execute each task
                }

                var allPromises = new All(promises);
                allPromises.then(function (r) { showIdentifyResults(r, tasks); });
            }

            function showIdentifyResults(r, tasks) {
                var results = [];
                var taskUrls = [];
                r = dojo.filter(r, function (result) {
                    return r[0];
                });
                for (i = 0; i < r.length; i++) {
                    results = results.concat(r);
                    for (j = 0; j < r.length; j++) {
                        taskUrls = taskUrls.concat(tasks.url);
                    }
                }
                results = dojo.map(results, function (result, index) {
                    var feature = result.feature;
                    var layerName = result.layerName;
                    var serviceUrl = taskUrls[index];
                    feature.attributes.layerName = result.layerName;

                    var template = new esri.InfoTemplate("", "Service Url: " + serviceUrl + "<br/><br/>Layer name: " + result.layerName + "<br/><br/> Object Id: ${OBJECTID}");
                    feature.setInfoTemplate(template);

                    var resultGeometry = feature.geometry;
                    var resultType = resultGeometry.type;
                    return feature;
                });

                if (results.length === 0) {
                    map.infoWindow.clearFeatures();
                } else {
                    map.infoWindow.setFeatures(results);
                }
                map.infoWindow.show(idPoint);
                return results;
            }

            function createIdentifyParams(layers, evt) {
                var identifyParamsList = [];
                identifyParamsList.length = 0;
                dojo.forEach(layers, function (layer) {
                    var idParams = new esri.tasks.IdentifyParameters();
                    idParams.width = map.width;
                    idParams.height = map.height;
                    idParams.geometry = evt.mapPoint;
                    idParams.mapExtent = map.extent;
                    idParams.layerOption = esri.tasks.IdentifyParameters.LAYER_OPTION_VISIBLE;
                    var visLayers = layer.visibleLayers;
                    if (visLayers !== -1) {
                        var subLayers = [];
                        for (var i = 0; i < layer.layerInfos.length; i++) {
                            if (layer.layerInfos.subLayerIds == null)
                                subLayers.push(layer.layerInfos.id);
                        }
                        idParams.layerIds = subLayers;
                    } else {
                        idParams.layerIds = [];
                    }
                    idParams.tolerance = 3;
                    idParams.returnGeometry = true;
                    identifyParamsList.push(idParams);
                });
                return identifyParamsList;
            }

        });
    </script>
</head>

<body>
    <div id="map"></div>
</body>

</html>
AndyMorgan1
New Contributor III

I have no problem with identifying multiple map services, but within two of the services there are grouped layers.  I cannot get results returned for sublayers.

For example see below, or image attached:

Water Layers  (= map service level)
- Water Valve
- Water Fire Hydrant
- Water Abandoned/Removed  (= layer group, not visible by default)
     - Fire Hydrant (A/R)
     - Water Valve (A/R)
     - Water Line (A/R)
- Water Line

Using the "LAYER_OPTION_VISIBLE" layerOption doesn't work.  The "Water Abandoned/Removed" group layer is not visible by default from the mxd settings, so users must make it visible by checking it on the TOC/Legend (widget by NLiu).  With the group layer and all sublayers checked, and within the visible scale range, nothing is returned in results.

I tried applying your code above with no success either.

My identify code is rather long, as I built a custom info window, but here's where I set the currently visible layers upon map "click" event.  It passes the correct ID's into the array [8,9,10] which equate to Fire Hydrant (A/R), Water Valve (A/R), and Water Line (A/R).  But Identify Task does not produce any results for these three layers.  It only works if I use LAYER_OPTION_ALL, but then I have the obvious problem of returning results from layers not currently visible.

function buildCurrentMapServiceLayerList(serviceLayer) {
             var lyrInfos = {};
             var hasVisibleLayers = false;
             dynamicLayerInfos = serviceLayer.createDynamicLayerInfosFromLayerInfos();
             array.forEach(dynamicLayerInfos, function (info) {
                 var i = {
                     id: info.id,
                     name: info.name
                 };
                 if (array.indexOf(serviceLayer.visibleLayers, info.id) > -1) {
                     i.visible = true;
                     hasVisibleLayers = true;
                 }
                 else {
                     i.visible = false;
                 }
                

                 if (!info.subLayerIds) {
                     lyrInfos[info.id] = i;
                 }
             });
             if (hasVisibleLayers === true) {
                 mapServiceInfos[serviceLayer.id] = lyrInfos;
             }
         }

Then, to create parameters and execute identify task...

                var serviceName = mapServiceInfos[idxName];
                 for (var idxLayer in serviceName) {   //loop through layers within the current map service 
                     var layer = serviceName[idxLayer];
                     if (layer.name.toUpperCase().indexOf("LABEL") == -1 && layer.visible == true) {
                         layersToIdentify.push(layer.id);
                     }
                 }

 
                 identifyParams.layerIds = layersToIdentify;
                 identifyParams.tolerance = 8;
                 identifyParams.returnGeometry = true;
                 identifyParams.layerOption = IdentifyParameters.LAYER_OPTION_VISIBLE;
                 identifyParams.width = map.width;
                 identifyParams.height = map.height;
                 identifyParams.geometry = event.mapPoint;
                 identifyParams.mapExtent = map.extent;
                 if (layersToIdentify.length > 0) {
                     var idDeferred = identifyTask.execute(identifyParams, function (idResults) {
                         processIdentifyResults(idResults, event);
                     });
                 }

(Using js api 3.10 against ArcGIS Server 10.0 services, soon to upgrade to 10.2.2)

0 Kudos
KenBuja
MVP Esteemed Contributor

I use

idParams.layerIds = layer.visibleLayers;

which gives me the list of visible layers to use in the IdentifyTask.

This works with the subgroups I have in one of my services (and I also use the TOC widget to turn them on.

identifymulti.png

AndyMorgan1
New Contributor III

Ken, thanks for confirming this scenario.  I happen to have a virtual server with 10.2.0 services running, and after substituting with a similar map service (also containing subgroups) it does indeed return the sublayers.

May I ask what API and Server combination you are using?  Just for additional reference. 

Much appreciated! 

0 Kudos
LucianaArrúa
New Contributor III

Hi!, I would like to know how to add context menu in each layer of the list to an attribute table is open and display it as flaps please! 

thanks

0 Kudos