get layer from webmap

5441
17
06-06-2020 03:12 PM
TroyBingaman
New Contributor

Hello,

I'm trying to learn the JS API.  I've been following through the tutorials and am currently on buffer and intersect geometry.

As I follow along sometimes I try to adjust things to further learn.  In this case, instead of using the example which uses a featureLayer, I want to do the same thing but on a layer found within a webMap.

So I am replacing this line:

var featureLayer = new FeatureLayer({ url: "https://services3.arcgis.com/GVgbJbqm8hXASVYi/arcgis/rest/services/Trails_Styled/FeatureServer/0" }); map.add(featureLayer);

with this:

var webmap = new WebMap({
portalItem: {
id: "***mywebmapid***"
}
});

var view = new MapView({
container: "viewDiv",
//*** UPDATE ***//
map: webmap
//center: [-118.80500,34.02700],
//zoom: 13
});

then instead of using featureLayer in the function, I am trying to use a layer withing the webMap.  I tried this:

var parksLayer = webmap.findLayerById("958f6534812a4407925a2a18a640b841");

and changed the one line to read:

return (result.graphic.layer === parksLayer);

I'm getting an error that says:  Uncaught (in promise) TypeError: Cannot read property 'graphic' of undefined
at  (pointing to this line   })[0].graphic; )

I'm not sure what I'm doing wrong here.  Can anyone point me in the right direction?

Thanks!!

0 Kudos
17 Replies
ChristopherKoenig
Esri Contributor

Hi,

A way you can find an individual layer within a WebMap is to use the allLayers property. The allLayers property is actually a Collection of all the layers in the WebMap which means all basemap layers, operational layers, ground layers as well as group layers and their children layers are included. 

Since the alLayers property is a Collection you can use the find method to find and return a layer by name. Below is the documentation on that property along with a sample on how to use it to find a layer by name:

Sincerely,

Chris

EricGardecki1
New Contributor III

Thanks for the reply.  I adjusted the script to use allLayers but am still getting the same error.  Here is the full applicable section of the code:

var parksLayer = webmap.allLayers.find(function(layer) {
return layer.title === "Parks";
});

var activeGraphic;

function findNearestGraphic(event) {
return view.hitTest(event).then(function (response) {
var graphic;
// Get the Trail graphics only
if (response.results.length) {
graphic = response.results.filter(function (result) {
return (result.graphic.layer === parksLayer);
})[0].graphic;           *************************************************************
}
// Only return new graphics are found
if (graphic) {
if (!activeGraphic || (activeGraphic.attributes.OBJECTID !== graphic.attributes.OBJECTID)) {
return graphic;
} else {
return null;
}
} else {
return null;
}
});
}

var bufferGraphic;

function drawBuffer(bufferGeometry) {
view.graphics.remove(bufferGraphic);
bufferGraphic = new Graphic({
geometry: bufferGeometry,
symbol: {
type: "simple-fill",
color: "rgba(0,0,0,0)",
outline: {
color: "rgba(0,0,0,.5)",
width: 1
}
}
});
view.graphics.add(bufferGraphic);
}

view.on("pointer-move", function(event){
findNearestGraphic(event).then(function(graphic){
if (graphic) {
activeGraphic = graphic;
var buffer = geometryEngine.geodesicBuffer(activeGraphic.geometry, .25, "miles");
drawBuffer(buffer);
}
});
});

The line with the error is marked with all the asterisks.  I do not understand what that line is doing exactly so I can't figure out what's wrong and why it doesn't like me using a webmap layer.

Also, was there anything wrong with using findLayerById instead of allLayers?

thanks

0 Kudos
Noah-Sager
Esri Regular Contributor

You might need to load() the layer first, or try a more asynchronous approach like in this example: ArcGIS API for JavaScript Sandbox 

EricGardecki1
New Contributor III

I don't think I understand.

So if I use your example, I would then have the layer in the map twice no?  I have a webmap pulled in with all its layers, then would load one individual layer again?

The point of what I'm trying to do is learn how to work with the layers within the webmap as opposed to bringing in individual layers.

Does this make sense? 

Thanks!

0 Kudos
UndralBatsukh
Esri Regular Contributor

Hi there, 

This error: 

Uncaught (in promise) TypeError: Cannot read property 'graphic' of undefined
at  (pointing to this line   })[0].graphic; )

is telling you that your hitTest result is not defined. Looking at the code, you are only getting the first result returned from the hitTest. Instead you should loop through all results came back from the hitTest until you find the feature you are looking for. See the example below. 

view.hitTest(event).then(function(response) {
  var results = response.results;
  // Check if a feature from the featurelayer was clicked on
  results.forEach(function(result) {
   if (result.graphic && result.graphic.layer === featureLayer){
      // do something
   }
  });
});

This sdk sample shows you how to loop through results of hittest. 

Hope this helps,

-Undral

0 Kudos
GeorgeAbraham
New Contributor III

Hi Undral Batsukh‌,

The Array.filter() will internally loop through all the elements and return you the filtered value and we just need the first result so that piece of code is fine.

Can do the same thing via forEach but its a more ES6 simplified code to write. The issue wouldn't be with that code.

0 Kudos
GeorgeAbraham
New Contributor III

Hi Troy Bingaman‌,

Before you go for your hitTest, it actually needs your screen point to check what graphic it is, etc.

Just a hunch that its not able to identify the graphics and hence the successive code is failing.

In your finNearestGraphic(event) function, create a screenPoint object and pass that for the hitTest

function findNearestGraphic(event) {

var screenPoint = {
x: event.x,
y: event.y
};

return view.hitTest(screenPoint).then(function (response) {
var graphic;
if (response.results.length) {

//Existing Code

}

//Existing Code

}

I have achieved the same in another application and above was my approach.

Another thing is to ensure that the view is loaded before even the mouse actions, so you could encapsulate the whole in 

view.when(function() {

//Code

}

0 Kudos
EricGardecki1
New Contributor III

The code I am using is straight out of the api tutorial.  The only adjustment I am making is to reference a layer within a webMap rather than a layer added via FeatureLayer.  Using the code as-is from the tutorial works just fine so I do not believe the problem would lie in the screen point.

I have to imagine it isn't finding the layer?

I tried wrapping the applicable code in the view.when but I still receive the same error.

P.S.  This topic was posted by me.  I was accidentally logged in as another user.  Feel free to tag me instead of that user.

Thanks for your reply!

0 Kudos
EricGardecki1
New Contributor III

I also tried the screen point suggestion and no change.

0 Kudos