AnsweredAssumed Answered

How do I get a table of Feature Layer attributes to show in a Grid?

Question asked by mbindl on Apr 9, 2020
Latest reply on Apr 10, 2020 by rscheitlin

I'm having trouble getting a grid element to display the data from a feature layer. I've been modifying the answer to this questionDisplay attribute table with JavaScript API ver 4.9?  by Robert Scheitlin, GISP

 

 Lidia Dudina did you get a feature layer to work with Robert's example?

 

I"m getting a Type Error on line 293 in the createGrid function. Not sure where I'm going wrong here.

 

Any help would be greatly appreciated. 

 

Thanks,
Mason

 

 

<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">
  <meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no">
  <title>dGrid - 4.9</title>

  <link rel="stylesheet" href="https://js.arcgis.com/4.14/esri/css/main.css">
  <script src="https://js.arcgis.com/4.9/"></script>
  <style>
    html,
    body,
    #viewDiv
{
      padding: 0;
      margin: 0;
      height: 100%;
      width: 100%;
      overflow: hidden;
    }

    #info,
    #gridDisplay
{
      position: absolute;
      bottom: 0;
      left: 0;
      height: 35%;
      background-color: white;
      border-color: grey;
      width: 100%;
      font-family: "Avenir Next W00", "Helvetica Neue", Helvetica, Arial, sans-serif;
      font-size: 14px;
    }

    #info {
      z-index: 90;
      font-size: 16px;
      padding-left: 20px;
    }

    #info * {
      padding-right: 20px;
    }

    #gridDisplay {
      z-index: 80;
    }

    .info {
      line-height: 20px;
      padding-left: 5px ! important;
    }

    .dgrid-header,
    .dgrid-header-row
{
      background-color: #eee;
      color: #57585A;
    }

    .dgrid-row-even {
      background-color: #F7F8F8;
    }

    .dgrid-row-odd {
      background-color: #EFEFEF;
    }

    .dgrid-selected {
      background: #B4DAF5;
    }

    .dgrid-row {
      border: none
    }
  </style>


  <script>
    require([
        "esri/config",
        "esri/WebMap",
        "esri/views/MapView",
        "esri/layers/FeatureLayer",
        "esri/Graphic",
        "esri/widgets/Legend",
        "esri/widgets/Expand",
        "esri/geometry/SpatialReference",
        "dgrid/OnDemandGrid",
        "dgrid/extensions/ColumnHider",
        "dojo/store/Memory",
        "dstore/legacy/StoreAdapter",
        "dgrid/Selection"
      ],
      function(
        esriConfig, WebMap, MapView, FeatureLayer, Graphic, Legend, Expand, SpatialReference,
        OnDemandGrid, ColumnHider, Memory, StoreAdapter, Selection
      ) {
        {
        esriConfig.portalUrl = "https://maps.trpa.org/portal";
            };
               
        let map, view, meadowLayerView, grid;
        const gridDiv = document.getElementById("grid");
        const infoDiv = document.getElementById("info");

        // create new map, view and csvlayer
        const gridFields = ["OBJECTID", "MeadowType", "Final_Rating",
           "Acres"
        ];
       
        const meadowLayer = new FeatureLayer({
            url: "https://maps.trpa.org/server/rest/services/SEZViewer_AssessmentUnits_Meadows/MapServer/0",
            outFields: gridFields
        });


        map = new WebMap({
            portalItem: {
              id: "6d740280f5e34698bae774b38cde6469"
            },
            layers: [meadowLayer]
          });

           
        view = new MapView({
            container: "viewDiv",
            map: map,
            highlightOptions: {
              color: "#2B65EC",
              fillOpacity: 0.4
            },
            padding: {
              bottom: infoDiv.clientHeight
            }
          });

          const legendExpand = new Expand({
            view: view,
            content: new Legend({
              view: view,
              style: "card"
            })
          });
          view.ui.add(legendExpand, "top-left");


        // create a new datastore for the on demandgrid
        // will be used to display attributes of selected features
        const dataStore = new StoreAdapter({
          objectStore: new Memory({
            idProperty: "OBJECTID"
          })
        });
        /****************************************************
         * Selects features from the layer that intersect
         * a polygon that user drew using sketch view model
         ****************************************************/

        function popGrid() {
          view.graphics.removeAll();
          if (meadowLayerView) {
            const query = {
              where: "1=1",
              outFields: ["*"]
            };

            // query graphics from the layer view. Geometry set for the query
            // can be polygon for point features and only intersecting geometries are returned
            meadowLayerView.queryFeatures(query).then(function(results) {
                const graphics = results.features;
                // if the grid div is displayed while query results does not
                // return graphics then hide the grid div and show the instructions div
                if (graphics.length > 0) {
                  gridDiv.style.zIndex = 90;
                  infoDiv.style.zIndex = 80;
                  document.getElementById("featureCount").innerHTML =
                    "<b>Showing attributes for " +
                    graphics.length.toString() + " features </b>"
                } else {
                  gridDiv.style.zIndex = 80;
                  infoDiv.style.zIndex = 90;
                }

                // get the attributes to display in the grid
                const data = graphics.map(function(feature, i) {
                  return Object.keys(feature.attributes)
                    .filter(function(key) {
                      // get fields that exist in the grid
                      return (gridFields.indexOf(key) !== -1);
                    })
                    // need to create key value pairs from the feature
                    // attributes so that info can be displayed in the grid
                    .reduce(function(obj, key) {
                      obj[key] = feature.attributes[key];
                      return obj;
                    }, {});
                });

                // set the datastore for the grid using the
                // attributes we got for the query results
                dataStore.objectStore.data = data;
                grid.set("collection", dataStore);
              })
              .catch(errorCallback);
          }
        }
        /************************************************
         * fires when user clicks a row in the grid
         * get the corresponding graphic and select it
         *************************************************/

        function selectFeatureFromGrid(event) {
          // close view popup if it is open
          view.popup.close();
          // get the ObjectID value from the clicked row
          const row = event.rows[0]
          const id = row.data.OBJECTID;

          // setup a query by specifying objectIds
          const query = {
            objectIds: [parseInt(id)],
            outFields: ["*"],
            returnGeometry: true,
            outSpatialReference: view.SpatialReference
          };

          // query the csvLayerView using the query set above
          meadowLayerView.queryFeatures(query).then(function(results) {
              const graphics = results.features;
              // remove all graphics to make sure no selected graphics
              view.graphics.removeAll();
              view.goTo(graphics[0].geometry);

              // create a new selected graphic
              const selectedGraphic = new Graphic({
                geometry: graphics[0].geometry,
                symbol: {
                  type: "simple-marker",
//                  style: "circle",
                  color: "orange",
                  size: "12px", // pixels
                  outline: { // autocasts as new SimpleLineSymbol()
                    color: [255, 255, 0],
                    width: 2 // points
                  }
                }
              });

              // add the selected graphic to the view
              // this graphic corresponds to the row that was clicked
              view.graphics.add(selectedGraphic);
            })
            .catch(errorCallback);
        }

        /************************************************
         * Creates a new grid. Loops through layer
         * fields and creates grid columns
         * Grid with selection and columnhider extensions
         *************************************************/

        function createGrid(fields) {
          var columns = fields.filter(function(field, i) {
            if (gridFields.indexOf(field.name) !== -1) {
              return field;
            }
          }).map(function(field) {
            if (field.name === "OBJECTID") {
              return {
                field: field.name,
                label: field.name,
                sortable: true,
                hidden: true
              };
            } else {
              return {
                field: field.name,
                label: field.alias,
                sortable: true
              };
            }
          });

          // create a new onDemandGrid with its selection and columnhider
          // extensions. Set the columns of the grid to display attributes
          // the hurricanes cvslayer
          grid = new(OnDemandGrid.createSubclass([Selection, ColumnHider]))({
            columns: columns
          }, "grid");

          // add a row-click listener on the grid. This will be used
          // to highlight the corresponding feature on the view
          grid.on("dgrid-select", selectFeatureFromGrid);
        }
       
        function errorCallback(error) {
          console.log("error:", error)
        }
       
        // create a grid with given columns once the layer is loaded
        meadowLayer.when(function() {
            // create a grid with columns specified in gridFields variable
            createGrid(meadowLayer.fields);

            // get a reference the meadowlayerview when it is ready.
            view.whenLayerView(meadowLayer).then(function(layerView) {
              meadowLayerView = layerView;
              popGrid();
            });
          })
          .catch(errorCallback);

      });
  </script>

</head>

<body>
  <div id="viewDiv">
    <div id="info">
      <span class="info">
        <b>Populating grid...</b>
      </span>
      <br />
    </div>
    <div id="gridDisplay">
      <span class="info" id="featureCount"></span>
      <div id="grid"></div>
    </div>
  </div>
</body>

</html>

Outcomes