fetch Proxy object '_fields' from FeatureLayer object

606
4
Jump to solution
08-26-2021 01:47 AM
diaconori
New Contributor III

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?

diaconori_0-1629967566753.png

 

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)

 

 

 

 

0 Kudos
1 Solution

Accepted Solutions
JohnGrayson
Esri Regular Contributor

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);
});

  

View solution in original post

0 Kudos
4 Replies
JohnGrayson
Esri Regular Contributor

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);
});

  

0 Kudos
diaconori
New Contributor III

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:

diaconori_0-1629994483832.png

Result of MapServer REST Services using JohnGrayson's answer:

diaconori_1-1629994522026.png

 

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);
                        }
                    }
                });
            });

 

 

0 Kudos
JohnGrayson
Esri Regular Contributor

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.

diaconori
New Contributor III

It definitively did. Thank you.

0 Kudos