Select to view content in your preferred language

Cluster popup browse features values is undefined

1185
2
Jump to solution
03-10-2022 09:17 PM
ShefaliMantri
New Contributor III

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>

 

 

 

0 Kudos
1 Solution

Accepted Solutions
UndralBatsukh
Esri Regular Contributor

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;
}

View solution in original post

2 Replies
UndralBatsukh
Esri Regular Contributor

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;
}
ShefaliMantri
New Contributor III

Thank you @UndralBatsukh

It resolve my issue

0 Kudos