Select to view content in your preferred language

PopupTemplate from Client Side Graphics Not Working

6453
14
Jump to solution
01-12-2017 09:05 AM
chuckfrank
Occasional Contributor

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>

0 Kudos
14 Replies
chuckfrank
Occasional Contributor

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>‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
DavidColey
Frequent Contributor

Yeah there you go. Much cleaner.  This will help others too for sure

0 Kudos
KevinCheriyan
Occasional Contributor

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 


--------------------------------------------------
Application Developer, GeoMarvel
0 Kudos
VincentJones
New Contributor II

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.

0 Kudos
VincentJones
New Contributor II

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.