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?
Solved! Go to Solution.
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);
}));
}
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>
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
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.
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.
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);
}));
}
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.
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));
Thank you! So do I need to set a third identify task for the attachments?
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.