Hi All,
I'm attempting to create a FeatureLayer from an array of graphics and have been able to get features to display on a map, but I'm not able to click on them to use the PopupTemplate. In earlier version of the js api 3.x I was able to get this to work, but I haven't had any success with version 4.2. I've attached all of my code and kept it as simple as possible. Does anybody know why the PopupTemplate isn't displaying?
Code Follows:
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no" />
<meta name="date" content="January 12, 2017" />
<title>Station Location Map</title>
<link rel="stylesheet" href="https://js.arcgis.com/4.2/esri/css/main.css" />
<style>
html, body {
height: 100%;
}
#viewDiv {
padding: 0%;
margin: 0%;
height: 100%;
width: 100%;
}
</style>
<script src="https://js.arcgis.com/4.2/"></script>
<script src="http://code.jquery.com/jquery-3.1.1.min.js" integrity="sha256-hVVnYaiADRTO2PzUGmuLJr8BLUSjGIZsDYGmIJLv2b8=" crossorigin="anonymous"></script>
<script>
function station(name, location, latitude, longitude, url) {
this.name = name;
this.location = location;
this.latitude = latitude;
this.longitude = longitude;
this.url = url
};
var stations = [];
stations.push(new station("Station 1", "Canisteo River", 42.1, -77.2, "http://www.google.com"));
stations.push(new station("Station 2", "Juniata River", 40.5, -78.0, "http://www.google.com"));
stations.push(new station("Station 3", "Chiques Creek", 40.2, -76.3, "http://www.google.com"));
console.log('Array is populated...')
require([
"esri/Basemap",
"esri/Map",
"esri/views/MapView",
"esri/layers/FeatureLayer",
"esri/layers/MapImageLayer",
"esri/geometry/Point",
"esri/Graphic",
"esri/PopupTemplate",
"esri/renderers/SimpleRenderer",
"esri/symbols/SimpleMarkerSymbol",
"esri/symbols/SimpleLineSymbol",
"esri/symbols/SimpleFillSymbol",
"esri/widgets/BasemapToggle",
"esri/widgets/Home",
"dojo/domReady!"],
function (
Basemap,
Map,
MapView,
FeatureLayer,
MapImageLayer,
Point,
Graphic,
PopupTemplate,
SimpleRenderer,
SimpleMarkerSymbol,
SimpleLineSymbol,
SimpleFillSymbol,
BasemapToggle,
Home
) {
var stationFeatureLayer;
var fields = [
{
name: "ObjectID",
alias: "ObjectID",
type: "oid"
}, {
name: "name",
alias: "name",
type: "string"
}, {
name: "location",
alias: "location",
type: "string"
}, {
name: "url",
alias: "url",
type: "string"
}];
var popupTemplate = new PopupTemplate({
title: "{name}",
content: [{
type: "fields",
fieldInfos: [{
fieldName: "location",
label: "Location",
visible: true
}, {
fieldName: "url",
label: "More info",
visible: true
}]
}]
});
var map = new Map({
basemap: "satellite"
});
var view = new MapView({
container: "viewDiv",
map: map,
zoom: 7,
center: [-77, 41.25]
});
// symbolization //
var simpleLineSymbol = new SimpleLineSymbol({
color: "black",
width: "1px",
style: "solid"
});
// Circle Marker (DEFAULT)
var simpleMarkerSymbolDefault = new SimpleMarkerSymbol({
style: "circle",
color: "red",
size: "12px",
outline: simpleLineSymbol
});
var stationsRenderer = new SimpleRenderer({
symbol: simpleMarkerSymbolDefault,
label: "Monitoring Site"
});
var basemapToggle = new BasemapToggle({
view: view,
nextBasemap: "streets"
});
basemapToggle.startup();
view.ui.add(basemapToggle, "top-right");
var home = new Home({
view: view
});
view.ui.add(home, "top-left");
var graphics = [];
view.then(function () {
console.log("view.then");
var i = 0;
for (s in stations) {
console.log(stations.latitude);
var pt = new Point(stations.longitude, stations.latitude);
var attr = { "ObjectID": i, "name": stations.name, "location": stations.location, "url": stations.url }
console.log(attr);
var graphic = new Graphic({
attributes: attr,
geometry: pt,
popupTemplate: popupTemplate
});
graphics.push(graphic);
i = i + 1;
}
featureLayer = new FeatureLayer({
source: graphics,
fields: fields,
objectIdField: "ObjectID",
renderer: stationsRenderer,
geometryType: "point", // Must be set when creating a layer from Graphics
popupTemplate: popupTemplate
});
console.log(featureLayer);
map.add(featureLayer);
});
});
</script>
</head>
<body>
<div id="viewDiv">
</div>
</body>
</html>
Solved! Go to Solution.
Hi David,
Using the graphics sample you supplied, I was able to get Popup Templates to work with an array of graphics. I'm not really sure what was causing the original problem with going the Feature Layer route, but I may revisit that another time. Originally, I was trying to manually create a Feature Layer because I thought it would give me better capabilities with selections and rendering. In some troubleshooting while I was coding I noticed that I needed to click at a very precise location in order to to trigger the popup, but I wasn't able to determine the cause, so I just did a complete re-write and the working code is below. My leading thoughts on what was going wrong with my original attempt would be the way I was populating the source with a function; creating a feature layer in the "view.then"; or possibly the way I was constructing my Popup Template. Thanks again for your help!
Final Solution - Different Approach that Uses Graphics Instead of Feature Layer Follows:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no">
<title>Test Map 4.2</title>
<!--ESRI JavaScript API-->
<link rel="stylesheet" href="https://js.arcgis.com/4.2/esri/css/main.css">
<!--ESRI JavaScript API-->
<script src="https://js.arcgis.com/4.2/"></script>
<style>
html,
body,
#viewDiv {
padding: 0;
margin: 0;
height: 100%;
width: 100%;
}
</style>
<script>
require([
"esri/Map",
"esri/views/MapView",
"esri/Graphic",
"esri/geometry/Point",
"esri/geometry/Polyline",
"esri/geometry/Polygon",
"esri/PopupTemplate",
"esri/symbols/PictureMarkerSymbol",
"esri/symbols/SimpleMarkerSymbol",
"esri/symbols/SimpleLineSymbol",
"esri/symbols/SimpleFillSymbol",
"esri/widgets/BasemapToggle",
"esri/widgets/Home",
"dojo/domReady!"
], function (
Map,
MapView,
Graphic,
Point,
Polyline,
Polygon,
PopupTemplate,
PictureMarkerSymbol,
SimpleMarkerSymbol,
SimpleLineSymbol,
SimpleFillSymbol,
BasemapToggle,
Home
) {
// populate the array
function station(name, location, latitude, longitude, url) {
this.name = name;
this.location = location;
this.latitude = latitude;
this.longitude = longitude;
this.url = url
};
var stations = [];
stations.push(new station("station 1", "Canisteo River", 42.1, -77.2, "http://www.esri.com/"));
stations.push(new station("station 2", "Frankstown Branch Juniata River", 40.5, -78.0, "http://www.esri.com/"));
stations.push(new station("station 3", "Chiques Creek", 40.2, -76.3, "http://www.esri.com/"));
var map = new Map({
basemap: "hybrid"
});
var view = new MapView({
center: [-77, 41.25],
container: "viewDiv",
map: map,
zoom: 8
});
var basemapToggle = new BasemapToggle({
view: view, // The view that provides access to the map's "streets" basemap
nextBasemap: "streets" // Allows for toggling to the "hybrid" basemap
});
// start the basemap toggle widget and add it to the view
basemapToggle.startup();
view.ui.add(basemapToggle, "top-right");
var home = new Home({
view: view
});
view.ui.add(home, "top-left");
// symbolization //
var simpleLineSymbol = new SimpleLineSymbol({
color: "black",
width: "1px",
style: "solid"
});
// Circle Marker (DEFAULT)
var simpleMarkerSymbol = new SimpleMarkerSymbol({
style: "circle",
color: "red",
size: "12px",
outline: simpleLineSymbol
});
var pt = new PopupTemplate({ // autocasts as new PopupTemplate()
title: "Station: {Station}",
content: [{
type: "fields",
fieldInfos: [{
fieldName: "Location"
}, {
fieldName: "Url"
}]
}],
});
// loop
for (s in stations) {
// First create a point geometry (this is the location of the Titanic)
var point = new Point({
longitude: stations[s].longitude,
latitude: stations[s].latitude
});
// Create an object for storing attributes related to the line
var pointAtt = {
Station: stations[s].name,
Location: stations[s].location,
Url: stations[s].url
};
// Create a graphic and add the geometry and symbol to it
var pointGraphic = new Graphic({
geometry: point,
symbol: simpleMarkerSymbol,
attributes: pointAtt,
popupTemplate: pt
});
// Add the graphics to the view's graphics layer
view.graphics.add(pointGraphic);
}
});
</script>
</head>
<body>
<div id="viewDiv">
</div>
</body>
</html>
Yeah there you go. Much cleaner. This will help others too for sure
Looks like this is still an issue with ArcGIS API for JavaScript 4.x. Feature Layer with a source of client side graphics cannot be interacted with on the webmap. PopupTemplate doesn't work in that you can't get a popup to appear. And also, hitTest() doesn't work, since the mapPoint doesn't recognize the features that are clicked on. See other post here from someone else a while back:
https://community.esri.com/thread/189210-viewhittest-returning-0-results
I managed to get this working (PopupTemplate on a feature layer with client side graphics) using version 4.11 and 4.12 of the API but it appears not to work again in any version since.
I finally tracked down what the issue was here. In my case I was reading the objectId from a data attribute and although a numeric value, it's type must have been considered string by the API; parsing as integer fixed the issue.