Select to view content in your preferred language

Combine Feature Layer Popup with Raster Pixel Identify Popup

2396
10
Jump to solution
09-27-2016 10:22 AM
LloydBronn
Frequent Contributor

I have a map service that contains a feature layer with attachments and raster layers. I would like to have a popup that can display the attachments and metadata when the user clicks on a feature, and displays pixel values when the raster layer is clicked on. I've used both of these examples Identify with Popup & Popup widget | ArcGIS API for JavaScript 3.18, and they work perfectly. I'm wondering if it would be possible to combine them into a single popup that only references the layer that's being clicked on?

0 Kudos
1 Solution

Accepted Solutions
RobertScheitlin__GISP
MVP Emeritus

Lloyd,

   Come to think about it I would do this:

function mapReady() {
                    map.on("click", executeIdentifyTask);
                    //create identify tasks and setup parameters
                    identifyTask = new IdentifyTask("yoururl");

                    identifyParams = new IdentifyParameters();
                    identifyParams.returnGeometry = true;
                    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;
                    promises = [];
                    identifyParams.tolerance = 1;
                    identifyParams.layerIds = [0];
                    promises.push(identifyTask.execute(identifyParams));
                    identifyParams.tolerance = 5;
                    identifyParams.layerIds = [13];
                    promises.push(identifyTask.execute(identifyParams));

                    var iPromises = new all(promises);
                    iPromises.then(lang.hitch(this, function (r) {
                      var idResults = [];
                      arrayUtils.map(r, function(response) {
                        arrayUtils.map(response, function(result) {
                          var feature = result.feature;
                          var layerName = result.layerName;
                          feature.attributes.layerName = layerName;
                          var iTemplate;
                          if(feature.attributes['Pixel Value']){
                            iTemplate = new InfoTemplate(layerName,
                                "Pixel Value is : " + feature.attributes['Pixel Value']);
                            feature.setInfoTemplate(iTemplate);
                          }else{
                            iTemplate = new InfoTemplate(layerName, "${*}");
                            feature.setInfoTemplate(iTemplate);
                          }
                          idResults.push(feature);
                        });
                      });
                      map.infoWindow.setFeatures(idResults);
                      map.infoWindow.show(event.mapPoint);
                    }));
                }‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

View solution in original post

0 Kudos
10 Replies
RobertScheitlin__GISP
MVP Emeritus

Lloyd,

   The two can not be combined as they are because they both are wanting to listen for a map click event and one will override the other. You can extend the pixel identify code to also include identifying the feature layer as well though, but you would lose the attachments portion. This would involve adding a second identifyTask class and set the featurelayer url as the url for the task and then use a dojo all to wait for both identify tasks to return before you process the results.

<!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>San Francisco</title>
    <link rel="stylesheet" href="https://js.arcgis.com/3.18/dijit/themes/claro/claro.css">
    <link rel="stylesheet" href="https://js.arcgis.com/3.18/esri/css/esri.css">
    <style>
        html,
        body {
            height: 100%;
            width: 100%;
            margin: 0;
            padding: 0;
        }

        .esriScalebar {
            padding: 20px 20px;
        }

        #map {
            padding: 0;
        }
    </style>

    <script src="https://js.arcgis.com/3.18/"></script>
    <script>
        var map;

        require([
                "esri/config",
                "esri/map",
                "esri/InfoTemplate",
                "esri/dijit/Popup",
                "esri/dijit/PopupTemplate",
                "esri/layers/FeatureLayer",
                "esri/symbols/SimpleMarkerSymbol",
                "esri/tasks/GeometryService",
                "dojo/dom-construct",
                "dojo/parser",
                "esri/Color",
                "esri/tasks/IdentifyTask",
                "esri/tasks/IdentifyParameters",
                "esri/layers/ArcGISDynamicMapServiceLayer",
                "dojo/_base/array",
                "dojo/promise/all",
                "dojo/_base/lang",
                "dijit/layout/BorderContainer",
                "dijit/layout/ContentPane",
                "dojo/domReady!"
            ],
            function(
                esriConfig, Map, InfoTemplate, Popup, PopupTemplate, FeatureLayer,
                SimpleMarkerSymbol, GeometryService, domConstruct, parser, Color,
                IdentifyTask, IdentifyParameters, ArcGISDynamicMapServiceLayer,
                arrayUtils, all, lang
            ) {
                var identifyTask, identifyTask2, identifyParams, promises;
                parser.parse();

                esriConfig.defaults.geometryService = new GeometryService("https://utility.arcgisonline.com/ArcGIS/rest/services/Geometry/GeometryServer");

                var popupOptions = {
                    markerSymbol: new SimpleMarkerSymbol("circle", 32, null,
                        new Color([0, 0, 0, 0.25])),
                    marginLeft: "20",
                    marginTop: "20"
                };
                //create a popup to replace the map's info window
                var popup = new Popup(popupOptions, domConstruct.create("div"));

                map = new Map("map", {
                    basemap: "topo",
                    center: [-81, 32],
                    zoom: 11,
                    infoWindow: popup
                });

                map.on("load", mapReady);

                function mapReady() {
                    map.on("click", executeIdentifyTask);
                    //create identify tasks and setup parameters
                    identifyTask = new IdentifyTask("http://sagisservices.thempc.org/saint/rest/services/Imagery/ElevationDEM/MapServer");
                    identifyTask2 = new IdentifyTask("http://sagisservices.thempc.org/saint/rest/services/CEMA/CEMA1/MapServer");

                    identifyParams = new IdentifyParameters();
                    identifyParams.tolerance = 1;
                    identifyParams.returnGeometry = true;
                    identifyParams.layerIds = [0];
                    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;
                    promises = [];
                    identifyParams.tolerance = 1;
                    promises.push(identifyTask.execute(identifyParams));
                    identifyParams.tolerance = 5;
                    promises.push(identifyTask2.execute(identifyParams));

                    var iPromises = new all(promises);
                    iPromises.then(lang.hitch(this, function (r) {
                      var idResults = [];
                      arrayUtils.map(r, function(response) {
                        arrayUtils.map(response, function(result) {
                          var feature = result.feature;
                          var layerName = result.layerName;
                          feature.attributes.layerName = layerName;
                          var iTemplate;
                          if(feature.attributes['Pixel Value']){
                            iTemplate = new InfoTemplate(layerName,
                                "Pixel Value is : " + feature.attributes['Pixel Value']);
                            feature.setInfoTemplate(iTemplate);
                          }else{
                            iTemplate = new InfoTemplate(layerName, "${*}");
                            feature.setInfoTemplate(iTemplate);
                          }
                          idResults.push(feature);
                        });
                      });
                      map.infoWindow.setFeatures(idResults);
                      map.infoWindow.show(event.mapPoint);
                    }));
                }

                var featureLayer = new FeatureLayer("http://sagisservices.thempc.org/saint/rest/services/CEMA/CEMA1/MapServer/0", {
                    mode: FeatureLayer.MODE_SNAPSHOT,
                    outFields: ["*"]
                });
                var rasterLayer = new ArcGISDynamicMapServiceLayer("http://sagisservices.thempc.org/saint/rest/services/Imagery/ElevationDEM/MapServer", {
                    opacity: .55
                });
                map.addLayers([featureLayer, rasterLayer]);
            });
    </script>
</head>

<body class="claro">
    <div data-dojo-type="dijit/layout/BorderContainer" data-dojo-props="design:'headline'" style="width: 100%; height: 100%; margin: 0;">
        <div id="map" data-dojo-type="dijit/layout/ContentPane" data-dojo-props="region:'center'" style="border:1px solid #000;padding:0;">
        </div>
    </div>
</body>

</html>
0 Kudos
LloydBronn
Frequent Contributor

Thank you for your help Robert, this is great. One issue I'm seeing is that both my feature layer and multiple rasters are part of the same service URL. Am I right in thinking that featurelayer is looking for an URL with a layer number "MapService/0," and the dynamic service layer is just looking for "MapService" Would I need an identify task for each layer, MapService/1,  MapService/2, etc? There is one feature with attachments, and probably 28 rasters

0 Kudos
RobertScheitlin__GISP
MVP Emeritus

Lloyd,

well that changes the logic immensely then. If all the data is in the same map service then you just need one Identify task and you would just change the 

identifyParams.layerIds = [0]; to include all the layerids you want to identify in that array.

0 Kudos
LloydBronn
Frequent Contributor

OK. I removed the second identify task and changed the identifyParams.layerIds = [0,13] since I'm testing with the feature layer and one raster. This didn't work, so I put both identify tasks back in. I clicked on one feature and got both infoTemplates in the popup, but I couldn't repeat this. I can only see the pixel value if I click anywhere else. I'm still fuzzy on how to enable the attachments. 

0 Kudos
RobertScheitlin__GISP
MVP Emeritus

Lloyd,

   Come to think about it I would do this:

function mapReady() {
                    map.on("click", executeIdentifyTask);
                    //create identify tasks and setup parameters
                    identifyTask = new IdentifyTask("yoururl");

                    identifyParams = new IdentifyParameters();
                    identifyParams.returnGeometry = true;
                    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;
                    promises = [];
                    identifyParams.tolerance = 1;
                    identifyParams.layerIds = [0];
                    promises.push(identifyTask.execute(identifyParams));
                    identifyParams.tolerance = 5;
                    identifyParams.layerIds = [13];
                    promises.push(identifyTask.execute(identifyParams));

                    var iPromises = new all(promises);
                    iPromises.then(lang.hitch(this, function (r) {
                      var idResults = [];
                      arrayUtils.map(r, function(response) {
                        arrayUtils.map(response, function(result) {
                          var feature = result.feature;
                          var layerName = result.layerName;
                          feature.attributes.layerName = layerName;
                          var iTemplate;
                          if(feature.attributes['Pixel Value']){
                            iTemplate = new InfoTemplate(layerName,
                                "Pixel Value is : " + feature.attributes['Pixel Value']);
                            feature.setInfoTemplate(iTemplate);
                          }else{
                            iTemplate = new InfoTemplate(layerName, "${*}");
                            feature.setInfoTemplate(iTemplate);
                          }
                          idResults.push(feature);
                        });
                      });
                      map.infoWindow.setFeatures(idResults);
                      map.infoWindow.show(event.mapPoint);
                    }));
                }‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
0 Kudos
LloydBronn
Frequent Contributor

This works as well. Maybe my feature points are too small? Occasionally I can click on a feature and get both infotemplates, but it's spotty. 

0 Kudos
RobertScheitlin__GISP
MVP Emeritus

Lloyd,

   Then you need to increase the identify tolerance for the second identify:

                function executeIdentifyTask(event) {
                    identifyParams.geometry = event.mapPoint;
                    identifyParams.mapExtent = map.extent;
                    promises = [];
                    identifyParams.tolerance = 1; //this is the tolerance for the rasters
                    promises.push(identifyTask.execute(identifyParams));
                    identifyParams.tolerance = 7; //this is the tolerance for the point features
                    promises.push(identifyTask2.execute(identifyParams));
0 Kudos
LloydBronn
Frequent Contributor

Thank you! So do I need to set a third identify task for the attachments?

0 Kudos
RobertScheitlin__GISP
MVP Emeritus

Lloyd,

   As I mentioned in the beginning using this route will lose the attachment ability.

Don't forget to mark this question as answered by click on the "Correct Answer" link on the reply that answered your question. 

0 Kudos