Hello Team,
ArcGIS javascript API 4.22 we are using.
In project we create custom content of popup template for each feature layer. When we turned on Cluster, cluster popup template is opened and on click of browse feature, we can browse individual features.
The issue is when we try to browse individual feature, the field value is undefined except object id.
Question- How to show feature's value in place of undefined
Attaching sample code - For layers1 we created custom popup content.
<html>
<head>
<meta charset="utf-8" />
<meta
name="viewport"
content="initial-scale=1,maximum-scale=1,user-scalable=no"
/>
<title>
Point clustering - basic configuration | Sample | ArcGIS API for
JavaScript 4.22
</title>
<style>
html,
body,
#viewDiv {
padding: 0;
margin: 0;
height: 100%;
width: 100%;
background: rgba(50,50,50);
}
#infoDiv {
padding: 10px;
}
</style>
<link
rel="stylesheet"
href="https://js.arcgis.com/4.22/esri/themes/dark/main.css"
/>
<script src="https://js.arcgis.com/4.22/"></script>
<script>
require([
"esri/Map",
"esri/layers/FeatureLayer",
"esri/layers/GeoJSONLayer",
"esri/views/MapView",
"esri/widgets/Legend",
"esri/widgets/Expand",
"esri/widgets/Home"
], (Map, FeatureLayer, GeoJSONLayer, MapView, Legend, Expand, Home) => {
// Configures clustering on the layer. A cluster radius
// of 100px indicates an area comprising screen space 100px
// in length from the center of the cluster
const clusterConfig = {
type: "cluster",
clusterRadius: "100px",
// {cluster_count} is an aggregate field containing
// the number of features comprised by the cluster
popupTemplate: {
title: "Cluster summary",
content: "This cluster represents {cluster_count}.",
fieldInfos: [
{
fieldName: "cluster_count",
format: {
places: 0,
digitSeparator: true
}
}
]
},
clusterMinSize: "24px",
clusterMaxSize: "60px",
labelingInfo: [
{
deconflictionStrategy: "none",
labelExpressionInfo: {
expression: "Text($feature.cluster_count, '#,###')"
},
symbol: {
type: "text",
color: "#004a5d",
font: {
weight: "bold",
family: "Noto Sans",
size: "12px"
}
},
labelPlacement: "center-center"
}
]
};
const layers1 = new FeatureLayer({
url: "https://sampleserver6.arcgisonline.com/arcgis/rest/services/USA/MapServer/0",
featureReduction: clusterConfig,
popupTemplate: {
title: "city",
content: popupListContent,
'outFields': ['*']
}
});
const layer = new GeoJSONLayer({
title: "Earthquakes from the last month",
url: "https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_month.geojson",
copyright: "USGS Earthquakes",
featureReduction: clusterConfig,
// popupTemplates can still be viewed on
// individual features
popupTemplate: {
title: "Magnitude {mag} {type}",
content: "Magnitude {mag} {type} hit {place} on {time}",
fieldInfos: [
{
fieldName: "time",
format: {
dateFormat: "short-date-short-time"
}
}
]
},
renderer: {
type: "simple",
field: "mag",
symbol: {
type: "simple-marker",
size: 4,
color: "#69dcff",
outline: {
color: "rgba(0, 139, 174, 0.5)",
width: 5
}
}
}
});
const layer1 = layer;
// background layer for geographic context
// projected to Alaska Polar Stereographic
const baseLayer = new FeatureLayer({
portalItem: {
id: "2b93b06dc0dc4e809d3c8db5cb96ba69"
},
legendEnabled: false,
popupEnabled: false,
renderer: {
type: "simple",
symbol: {
type: "simple-fill",
color: [65, 65, 65, 1],
outline: {
color: [50, 50, 50, 0.75],
width: 0.5
}
}
},
spatialReference: {
wkid: 5936
}
});
const map = new Map({
layers: [baseLayer, layer, layers1]
});
const view = new MapView({
container: "viewDiv",
extent: {
spatialReference: {
wkid: 5936
},
xmin: 1270382,
ymin: -1729511,
xmax: 2461436,
ymax: -953893
},
spatialReference: {
// WGS_1984_EPSG_Alaska_Polar_Stereographic
wkid: 5936
},
constraints: {
minScale: 15469455
},
map: map
});
view.ui.add(
new Home({
view: view
}),
"top-left"
);
const legend = new Legend({
view: view,
container: "legendDiv"
});
const infoDiv = document.getElementById("infoDiv");
view.ui.add(
new Expand({
view: view,
content: infoDiv,
expandIconClass: "esri-icon-layer-list",
expanded: false
}),
"top-left"
);
const toggleButton = document.getElementById("cluster");
// To turn off clustering on a layer, set the
// featureReduction property to null
toggleButton.addEventListener("click", () => {
let fr = layer.featureReduction;
let fr1 = layers1.featureReduction;
layers1.featureReduction =
fr1 && fr1.type === "cluster" ? null : clusterConfig;
layer.featureReduction =
fr && fr.type === "cluster" ? null : clusterConfig;
toggleButton.innerText =
toggleButton.innerText === "Enable Clustering"
? "Disable Clustering"
: "Enable Clustering";
});
function popupListContent(feature) {
const tableContent = document.createElement("table");
tableContent.classList.add('tablelayout');
tableContent.classList.add('esri-widget__table');
let infoTamplateData = "";
let object = feature.graphic.attributes;
const fieldArr = [];
if (feature.graphic.layer && feature.graphic.layer.fields) {
feature.graphic.layer.fields.forEach(element => {
fieldArr.push(element.name);
});
}
fieldArr.forEach((f) => {
infoTamplateData += "<tr label= " + f + "><th class='esri-feature__field-header' >" +
f + " </th><td class='esri-feature__field-data'>" + object[f] + "</td> </tr>";
});
tableContent.innerHTML = infoTamplateData;
return tableContent;
}
});
</script>
</head>
<body>
<div id="viewDiv"></div>
<div id="infoDiv" class="esri-widget">
<button id="cluster" class="esri-button">Disable Clustering</button>
<div id="legendDiv"></div>
</div>
</body>
</html>
Solved! Go to Solution.
Hi there,
So in your example, your layer will always have null values for all features except for the objectId. You can change this by setting the outFields property on the FeatureLayer so the layer fetches attributes for additional fields. I changed it so that it fetches attributes for all fields.
const layers1 = new FeatureLayer({
url: "https://sampleserver6.arcgisonline.com/arcgis/rest/services/USA/MapServer/0",
featureReduction: clusterConfig,
outFields: ["*"],
popupTemplate: {
title: "city",
content: popupListContent
}
});
Then in your popupListContent, you can check if the feature has null values as shown below:
function popupListContent(feature) {
const tableContent = document.createElement("table");
tableContent.classList.add('tablelayout');
tableContent.classList.add('esri-widget__table');
let infoTamplateData = "";
let object = feature.graphic.attributes;
const fieldArr = [];
if (feature.graphic.layer && feature.graphic.layer.fields) {
feature.graphic.layer.fields.forEach(element => {
// check if the feature has values
if (feature.graphic.attributes[element.name] && feature.graphic.attributes[element.name] !== null){
fieldArr.push(element.name);
}
});
}
fieldArr.forEach((f) => {
infoTamplateData += "<tr label= " + f + "><th class='esri-feature__field-header' >" +
f + " </th><td class='esri-feature__field-data'>" + object[f] + "</td> </tr>";
});
tableContent.innerHTML = infoTamplateData;
return tableContent;
}
Hi there,
So in your example, your layer will always have null values for all features except for the objectId. You can change this by setting the outFields property on the FeatureLayer so the layer fetches attributes for additional fields. I changed it so that it fetches attributes for all fields.
const layers1 = new FeatureLayer({
url: "https://sampleserver6.arcgisonline.com/arcgis/rest/services/USA/MapServer/0",
featureReduction: clusterConfig,
outFields: ["*"],
popupTemplate: {
title: "city",
content: popupListContent
}
});
Then in your popupListContent, you can check if the feature has null values as shown below:
function popupListContent(feature) {
const tableContent = document.createElement("table");
tableContent.classList.add('tablelayout');
tableContent.classList.add('esri-widget__table');
let infoTamplateData = "";
let object = feature.graphic.attributes;
const fieldArr = [];
if (feature.graphic.layer && feature.graphic.layer.fields) {
feature.graphic.layer.fields.forEach(element => {
// check if the feature has values
if (feature.graphic.attributes[element.name] && feature.graphic.attributes[element.name] !== null){
fieldArr.push(element.name);
}
});
}
fieldArr.forEach((f) => {
infoTamplateData += "<tr label= " + f + "><th class='esri-feature__field-header' >" +
f + " </th><td class='esri-feature__field-data'>" + object[f] + "</td> </tr>";
});
tableContent.innerHTML = infoTamplateData;
return tableContent;
}
Thank you @UndralBatsukh
It resolve my issue