I have implemented a widget tool for our ArcGIS Enterprise solution, similar to the SelectLayerByAttribute tool from ArcGIS Pro, however, I am having trouble trying to get the information regarding the fields. The provided information in the documentation and the forums are not up to date, as all suggested answers do not work, despite any service url that is being provided.
I can see, that the information is there, but hidden by a proxy object. If the web map is using a FeatureServer REST service, we are able to fetch the '_fields' and deconstruct the proxy object, but if the web map is using a MapServer REST service, we are not able to even call the property and store it in a variable. Any solutions to this?
Code:
this.layerStructure.traversal((layerNode) => {
let featureLayerUrl = layerNode?._layerInfo?.layerObject?.url;
let featureLayer = new FeatureLayer(featureLayerUrl);
console.log("featureLayer._fields", featureLayer._fields);
}
Exception:
ReferenceError: _fields is not defined
at dno_presenter.js?wab_dv=2.20:215
at LayerNode.js?wab_dv=2.20:127
at Object.traversal (LayerInfo.js?wab_dv=2.20:156)
at Object.traversal (LayerNode.js?wab_dv=2.20:126)
at Object._traversal (LayerStructure.js?wab_dv=2.20:124)
at Object.traversal (LayerStructure.js?wab_dv=2.20:146)
at Object.initLayers (dno_presenter.js?wab_dv=2.20:212)
at Object.initializeLayersWithFields (dno_presenter.js?wab_dv=2.20:508)
at Object.initComponents (dno_presenter.js?wab_dv=2.20:80)
at Object.initPresenter (Widget.js?wab_dv=2.20:22)
Solved! Go to Solution.
When using JS API 3.x, the way to wait for a layer to be loaded is like this:
featureLayer.on("load", ()=> {
console.info(featureLayer.fields);
});
When using JS API 3.x, the way to wait for a layer to be loaded is like this:
featureLayer.on("load", ()=> {
console.info(featureLayer.fields);
});
You're a legend! You made it work regardless of them being either FeatureServer REST Services or MapServer REST Services. Thank you so much.
Result of FeatureServer REST Services using JohnGrayson's answer:
Result of MapServer REST Services using JohnGrayson's answer:
May I please ask what and why should we 'wait' for a layer to be loaded. Aren't they supposed to be loaded upon instantiation of the FeatureLayer object through it's constructor? I mean, I can see that the _fields property exist as a proxy object, but I can't fetch it without using your approach with the load-function. This is the code that works now with the accepted answer:
this.layerStructure.traversal((layerNode) => {
let layerServiceUrl = layerNode?._layerInfo?.layerObject?.url;
let featureLayer = new FeatureLayer(layerServiceUrl);
featureLayer.on("load", () => {
console.info("fields", featureLayer.fields);
let fieldsProxy = featureLayer.fields;
if (fieldsProxy != null || undefined) {
// Deconstructing the Handler and the Target object within the Proxy-object.
let fieldsTarget = JSON.parse(JSON.stringify(fieldsProxy));
if (fieldsTarget != null || undefined) {
console.log(layerNode.title, fieldsTarget);
}
}
});
});
I'm not familiar with the WAB internals so I can't speak to all the 'proxy' related stuff. However, when working with layers coming from services it is common practice to wait for the layer to be loaded. Many times layers are accessed via a layer item (instead of a URL) which might have overrides to some properties defined in the service, so after retrieving the service level information we'd have to then override those properties after retrieving the information from the layer item, which happens asynchronously. The same applies to accessing a layer in a web map, which might have overrides of its own. So, to ensure we don't work with properties that will change depending on how the layer was accessed, we instead wait for all the overrides to be applied (the load event) before working with the properties. I hope this helps.
It definitively did. Thank you.