Hello, I've probably encountered a performance issue with the Layer List widget in api version 4.16+ (version 4.15 and below is fine). After a research, I came to the conclusion that the render method of the widget is called too often, so there is a drastic slowdown of the view (lagging, long rendering time, almost 1000ms). In the Layer List sample on your site everything works fine. I use 10 or more widgets and about 10 layers in the map application, can it be related to that?
I am also experiencing issues with the performance of the layer list;
The listItemCreatedFunction function seems to be called multiple times for each item. Possibly related to the multiple render calls.
With many items in the list the whole view can lock up for 5 seconds or longer every time a layer is added or remove from the scene.
Any update on this? I am having the same isues. I have a layerlist widget with embedded legend. I have many layers in my map. When the view loads the listItemCreatedFunction gets called over 1000 times. I don't have that many layers in my map. It also gets called by other widgets. I have the sketch widget in my map and the listItemCreatedFunction gets called on every layer multiple times every time I click a point with the sketch tool. Apparently this happens with the select tool and measure tool as well (https://community.esri.com/t5/arcgis-api-for-javascript/problem-sketchviewmodel-create-fires-legend-...).
@_____ why does the listItemCreatedFunction get called so frequently? It is killing our apps.
No word on this? I have the same problem using 4.18. Using an array seems to handle it, but of course it's always best to fix a problem at the root.
let arrListItemCreated = [];
layerList = new LayerList({
view: mapView,
listItemCreatedFunction: layerListActions,
container: "layerListDiv"
});
function layerListActions(event) {
if (arrListItemCreated.indexOf(event.item.title) > -1) {
return false;
} else {
arrListItemCreated.push(event.item.title);
}
...
It seems this problem might be worse in 4.19. I just upgraded and my map which was working okay is now barely functional. I've pinpointed it to the listItemCreatedFunction and specifically adding a legend to the content panel. If I disable that part peformance is great. The function still gets called repeatedly but it's not a performance issue. @Andy_Morgan can you explain how your array works above? I'm not quite following it. Thanks!
Hi @NilsBabel1, since we cannot prevent the "listItemCreatedFunction" handler from being called over and over, my only thought was to have it exit if it's already been called for the current layer.
So my example points to a function (ex: "layerListActions") when defining the "new LayerList":
listItemCreatedFunction: layerListActions
This function is called whenever a list item is created, whether it's the 1st...18th...or 999th time for that same layer. If it's the first time, the layer's (unique) title is added to this array to essentially check it off the list. If we find the layer's title is already added to the array [ arrListItemCreated.indexOf(event.item.title) > -1 ] then we exit the handler completely. Basically don't do anything and move on, since it's already had some code applied.
Here's my full function, if it means anything more. I'm just checking for a certain layer to know if it's turned on (visible). If so, I'm programatically turning on a hidden feature layer. Not a typical case for most people, but it was necessary because I'm pulling in data on the fly from another source.
Anyway, hope this explains the use of the array and my logic.
function layerListActions(event) {
if (arrListItemCreated.indexOf(event.item.title) > -1) {
return false;
} else {
arrListItemCreated.push(event.item.title);
}
if (event.item && event.item.layer) {
const item = event.item;
const layer = item.layer;
item.open = item.visible;
let lyrVEPByExerciseDate = app.Functions.getLayerFromTitle(app.mapImgLyrUtilMap, "VEP by Exercised Date");
if (!uniqueParentItems.indexOf(item.title) > -1) {
uniqueParentItems.push(item.title);
item.watch("visible", function (event) {
if (app.dynamicFeatLyrVEP && (item.title === "VEP by Exercised Date" || item.title === "Valve Exercise Program")) {
if (event == true) {
if (lyrVEPByExerciseDate.visible == true) {
app.dynamicFeatLyrVEP.visible = true;
}
} else {
app.dynamicFeatLyrVEP.visible = false;
}
}
});
}
}
}
Super, thanks for the explanation. I get it now. So it essentially just runs once. Does this still improve performance?
You're welcome. That's correct, it's applying your function once for each layer's creation.
I'm not sure it'll be a noticeable improvement in performance, but it's a must for logic if you only want something done once...or if you're simply trying to debug and you don't want to unnecessarily hit a breakpoint for the same layer multiple times. That's what was annoying me. I just think it's the proper way to handle it, unless they change the API.
Thanks again. This is the only way for me to keep the legend in the layerlist. I'm using Esri's sample for that which seems very simple until you dig into it. It actually creates a separate legend widget for each layer in the map, within the layerlist created function. I have dozens of layers in my map, so when the function runs over and over again it kills my performance. No legend at all is best but this helps tremendously. I can't understand how esri has programmed this function like this on purpose.
ESRI states at 4.24 releasing July 22' should fix the issue of the Layer List, "Should".#BUG-000147907