I am trying to create a map to which users can add layers from ArcGIS data. They click a button, which opens a modal. In the modal, they enter the URL of the ArcGIS layer, choose a colour for the layer, and enter any text as a name for the layer. Then they click a button in the modal to close the modal and add the layer to both the map and the legend. (The legend also represents the order of the layers, so the first layer in the legend is visually on top of the others in the map, while the bottom one is below all the others, etc.)
I have run into a problem when adding an ArcGIS layer that contains polygons. When I add it to the map via the modal, sometimes nothing actually appears on the map. It seems to be that if I have a brand new empty map and add the layer, it will show up, but if, for example, I have just deleted another ArcGIS layer from the map and try to add this layer, it does not show up. However, when I reload the page using my web browser, it shows up. Also, if I use my program's UI controls to reload the map (for example, by loading a different map and then loading this one again), it shows up.
Alas, it's worse for a client, who is reporting that the layer never shows up on the map, no matter what!
Because of the client's issue, I have to assume that the issue isn't a matter of adding the layer versus loading a map that already has the layer: rather, it has to do with the timings of the layer getting its data versus actually being drawn on the map.
My map page actually does many other things, so the code is a bit of a large, complex maze. I'll share what I think is relevant here, but if you need to see more, let me know.
function ysisoftArcGISMap(map, url, color, layerID, order, isFromAdd, arcGisToken) {
var arcLayer = L.esri.featureLayer({
url: url,
pane: layerID,
token: arcGisToken,
pointToLayer: function (feature, latlng) {
let marker;
let markerOptions;
markerOptions = {
radius: 6,
fillColor: color,
color: '#000',
weight: 5,
opacity: 0.7,
fillOpacity: 0.6
};
marker = L.circleMarker(latlng, markerOptions);
return marker;
},
style: function () { return { color: color, weight: 3 }; },
});
if (!arcGisLayerIDs.includes(layerID)) {
addMapLayerToMap(arcLayer, layerID, false);
arcGisLayerIDs.push(layerID);
}
arcLayer.bindPopup(function (e) {
var props = "";
for (var propertyName in e.feature.properties) {
props += propertyName + ":{" + propertyName + "}<br>";
}
return L.Util.template(props, e.feature.properties)
});
arcLayer.once("load", function (evt) {
arcLayer.query().bounds(function (error, latlngbounds) {
if (layerID == lastLayerID) {
map.fitBounds(latlngbounds);
}
});
});
arcLayer.getAttribution = function () {
return layerID;
};
return arcLayer;
}
function addMapLayerToMap(geoJsonLayer, layerID, isSearchable) {
removeOldLayer(layerID);
var orderedMapLayer = $.grep(OrderedMapLayers, function (layer) { return layer.ID == layerID; });
if (orderedMapLayer.length > 0) {
layers.push(geoJsonLayer);
if (orderedMapLayer[0].IsVisible) {
map.addLayer(geoJsonLayer);
// [omitted code for when isSearchable == true]
}
}
if (orderedMapLayer[0].Order == OrderedMapLayers[OrderedMapLayers.length - 1].Order) {
isInitialLoad = false;
}
}
function removeOldLayer(layerID) {
for (var i = layers.length - 1; i >= 0; --i) {
var oldLayer = layers[i];
if (oldLayer.getAttribution) {
if (oldLayer.getAttribution() === layerID) {
map.eachLayer(function (layer) {
if (layer.options.pane == layerID) {
map.removeLayer(layer);
}
});
layers.splice(i, 1);
}
}
}
}
Things I have tried that do not work:
- manually trigger the 'load' of the layer >> does not fix problem; causes console error re: "arcLayer.triggerEvent() is not a function" (note: it also messes up the getAttribution() function so that it returns null, which breaks other code)
- call arcLayer.refresh() >> does not fix problem
- nest various things in setTimeout() >> does not fix problem
- using event listener for "data:loaded" >> never triggers, so it does nothing
- force the map to refresh using invalidateSize() >> does not fix problem
I've noticed something weird about ArcGIS layers, which is that a listener for on('load') will not trigger until the layer has been added to the map. I'm not sure whether this has anything to do with the trouble I'm having.
Also notable is the fact that the .query().bounds call returns unexpectedly enormous numbers (roughly 100,000 times larger than normal latitudes and longitudes). However, this seems to happen regardless of whether the polygons show on the map, so I'm not sure whether it's a clue to the underlying problem or just an unrelated issue.