Access polygon features with pointer events

356
10
Jump to solution
a month ago
ArianaToth
New Contributor III

Hi, I'm trying to modify the Access features with pointer events sample code from the ArcGIS Developers site. I want it to work with an existing webmap and with a polygon layer instead of a line. I've run the code through ChapGPT, which had me make some changes from the original structure, but the code isn't working either way. (Feature layer url and portal item id have been removed from the code below, but both do load in codepen.)

Any help would be much appreciated.

 

<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" />
    <title>Access features with pointer events | RH Planning Areas</title>

    <style>
      html,
      body,
      #viewDiv {
        padding: 0;
        margin: 0;
        height: 100%;
        width: 100%;
      }

      #info {
        background-color: black;
        opacity: 0.75;
        color: lightBlue;
        font-size: 18pt;
        padding: 8px;
        visibility: hidden;
      }
    </style>

    <link rel="stylesheet" href="https://js.arcgis.com/4.29/esri/themes/light/main.css" />
    <script src="https://js.arcgis.com/4.29/"></script>

    <script>
      require(["esri/WebMap", "esri/views/MapView", "esri/layers/FeatureLayer", "esri/symbols/SimpleFillSymbol"],
      (WebMap, MapView, FeatureLayer, SimpleFillSymbol) => {
        
        const PlanningAreasLayer = new FeatureLayer({
          url: "https://.../FeatureServer/0",
          outFields: ["*"]
        });

        const webmap = new WebMap({
          portalItem: {
            id: "itemID",
            portal: "https://www.arcgis.com",
            layers: [PlanningAreasLayer]
          }
        });

        const view = new MapView({
          container: "viewDiv",
          map: webmap,
          center: [-83.1563078,42.6645259],
          zoom: 12,
          highlightOptions: {
            color: "lightBlue"
          }
        });
        
        view.ui.add("info", "top-right");
        
        view
          .when()
          .then(() => {
            return PlanningAreasLayer.when();
          })
          .then((layer) => {
            const renderer = layer.renderer.clone();
            const fillSymbol = {
              type: "simple-fill",
              color: [255, 0, 255, 0], //transparent fill
              outline: {
                color: [255, 0, 0, 0], //red
                width: 4
              }
            };
          renderer.symbol = fillSymbol;
          layer.renderer = renderer;
                  

            // Set up an event handler for pointer-down (mobile)
            // and pointer-move events (mouse)
            // and retrieve the screen x, y coordinates
            return view.whenLayerView(layer);
          })
          .then((layerView) => {
            view.on("pointer-move", eventHandler);
            view.on("pointer-down", eventHandler);

            function eventHandler(event) {
              // only include graphics from PlanningAreasLayer in the hitTest
              const opts = {
                include: PlanningAreasLayer
              }
              // the hitTest() checks to see if any graphics from the PlanningAreasLayer
              // intersect the x, y coordinates of the pointer
              view.hitTest(event, opts).then(getGraphics);
            }
            let highlight, currentName;

            function getGraphics(response) {
              // the topmost graphic from the PlanningAreasLayer
              // and display select attribute values from the
              // graphic to the user
              if (response.results.length) {
                const graphic = response.results[0].graphic;
                const attributes = graphic.attributes;
                const areaName = attributes.Neighbor_1;
                const mapLink = attributes.Neighborho
                const id = attributes.OBJECTID;
                
                if (highlight && currentName !== areaName) {
                  //Check if a highlight exists (is not null or undefined)
                  //Checks if the current name is not equal to the name
                  //If true, name has changed so highlight should be removed
                  //If condition is true, execute the following code
                  highlight.remove(); //Remove the highlight from the graphic
                  highlight = null; //Set the highlight variable to null
                  return; //Exit the current function
                }
                
                if (highlight) {
                  const query = layerView.createQuery();
                  query.where = "NAME = '" + areaName + "'";
                  layerView.queryObjectIds(query).then((ids) => {
                    if (highlight) {
                      highlight.remove()
                    }
                    highlight = layerView.highlight(ids);
                    currentName = areaName;
                  })
                }
                
                //diplay information about the feature
                document.getElementById("info").style.visibility = "visible";
                document.getElementById("name").innerHTML = areaName;
                document.getElementById("link").innerHTML = mapLink;

              } else {
                // remove the highlight if no features are
                // returned from the hitTest
                if (highlight){
                  highlight.remove();
                  highlight = null;
                }
                document.getElementById("info").style.visibility = "hidden";
              }
            }
          });
      });
    </script>
  </head>

  <body>
    <div id="viewDiv"></div>
    <div id="info">
      <span id="name"></span> <br />
      <span id="link"></span>
    </div>
  </body>
</html>
--Ariana
0 Kudos
1 Solution

Accepted Solutions
UndralBatsukh
Esri Regular Contributor

Thanks for the codepen. 

A few things. First you already have the layer in your webmap. So there is no need to add another instance of it to your map. You can simply get the instance of the layer once the webmap is loaded. Then you have to set the outFields of the layer to all.  I sent you the modified codepen directly.

View solution in original post

10 Replies
UndralBatsukh
Esri Regular Contributor

What is the error you are getting? Looks like the query might not be running successfully just looking at your code.  Here you are saying the areaName is coming from Neighbor_1 field.  

 const areaName = attributes.Neighbor_1;

 

But later you are using the following query where the field name is NAME.  Which one is it?

 query.where = "NAME = '" + areaName + "'";

 

0 Kudos
ArianaToth
New Contributor III

I don't know JavaScript well so I thought I was inputting a string, not a variable with "NAME." I've changed that to "areaName" as well but I still don't get features to show on my map.

The message in the console is: 

"[esri.views.2d.layers.MediaLayerView2D]" // [object Object]
{
"name": "element-load-error",
"message": "Element cannot be displayed",
"details": "[object]"
}

--Ariana
0 Kudos
UndralBatsukh
Esri Regular Contributor

This error has nothing to do with the query action. The error is saying you have a MedialLayer in your app and that its media element cannot be displayed. You should remove the MediaLayer and start with a simpler app.

0 Kudos
ArianaToth
New Contributor III

I turned off the media layer and now I get zero warnings or errors in the console. But I still don't get any popups either. 

--Ariana
0 Kudos
UndralBatsukh
Esri Regular Contributor

What exactly are you trying to do? The sample you referenced does not display popup. It rather displays just a few info in a DIV tag as user moves the mouse over the features. Can you provide a working codepen so that I can help you further?

0 Kudos
ArianaToth
New Contributor III

Yes, that's what I mean by pop-up. It should display 2 attribute values and highlight the feature. Right now it does neither.

--Ariana
0 Kudos
UndralBatsukh
Esri Regular Contributor

I won't be able to help without an actual reproducible case. Can you provide one? 

0 Kudos
UndralBatsukh
Esri Regular Contributor

Thanks for the codepen. 

A few things. First you already have the layer in your webmap. So there is no need to add another instance of it to your map. You can simply get the instance of the layer once the webmap is loaded. Then you have to set the outFields of the layer to all.  I sent you the modified codepen directly.

ArianaToth
New Contributor III

I just had time to look at this some more and I realized that the attributes are showing up in the info Div but the layer still isn't highlighting. Can you please help with that?

--Ariana
0 Kudos