WAB FeatureLayer constructor throwing TypeError: Circular reference in value argument not supported

3100
1
Jump to solution
09-23-2015 08:35 PM
GarySinner
New Contributor III

I’ve run into an exception trying to create a FeatureLayer with the results of a spatial query.  The exception stack trace looks like this:

TypeError: Circular reference in value argument not supported

  at b.toJson

  at _initLayer

  at Anonymous function

  at _initFeatureLayer

  at constructor

  at h.around.advice

  at h

  at Anonymous function

  at _createResultsFeatureLayer  (my function)

I’ve found several posts that describe circular reference issues with serializing graphics to JSON.  Unfortunately none of them seem to fit my predicament.  When I look at the FeatureLayer object, all of the graphics contain a reference for the _graphicsLayer, which includes the same collection of graphics with each graphic containing a reference to the _graphicsLayer, etc.  Seems infinitely recursive/circular.  "The wheels on the bus go ‘round and ‘round…"  I am not sure if this is the issue or not – it could be completely unrelated.  In any case, I’m not sure how to break the cycle or resolve the exception.  Hopefully someone out there might have an answer, or at least some suggestions for things to try.

The attached zip contains a custom widget “CircularReference” that can be used to reproduce the problem.

To include the widget:

  • Drop the CircularReference folder from the zip into the widgets folder
  • Add the CircularReference to the app’s config.json file, editing index as appropriate.

"widgetPool": {

    "widgets": [

        {

                 "uri": "widgets/CircularReference/Widget",

                 "version": "1.3",

                 "id": "widgets/CircularReference/Widget_35",

                 "name": "CircularReference",

                 "label": "Circular Reference",

                 "index": 2

        },

  • Edit the searchLayers element in the CircularReference/config.json file to reference at least two dynamic map service layers in your map.  These could be from more than one map service, or multiple layers in a single map service.  The values for each layer should be self-explanatory.  Be sure to include the layer index at the end of the url.  In my test app I was using a sample Esri map service that has four layers in it.  If you want to use the config.json file as-is, be sure your webmap includes this map service.

"searchLayers": [

{

"mapServiceName""USA",

"name": "Cities",

"url": "http://sampleserver6.arcgisonline.com/arcgis/rest/services/USA/MapServer/0"

},

{

"mapServiceName""USA",

"name": "Highways",

"url": "http://sampleserver6.arcgisonline.com/arcgis/rest/services/USA/MapServer/1"

},

{

"mapServiceName""USA",

"name": "States",

"url": "http://sampleserver6.arcgisonline.com/arcgis/rest/services/USA/MapServer/2"

},

{

"mapServiceName""USA",

"name": "Counties",

"url": "http://sampleserver6.arcgisonline.com/arcgis/rest/services/USA/MapServer/3"

}

],

After getting everything configured, the workflow to generate the exception is as follows:

  • Zoom to an area of the map that has features from multiple layers in the CircularReference’s config.json searchLayers collection.
  • Click on the Circular Reference button.
  • Click on the search within map extents button.
  • This should kick off the search.  The runSpatialQueries() function loops over the specified layers and kicks off a search on each layer.
  • The search results wind up in the processResults() function that fills out a simple tree control.
  • Clicking on one of the results in the tree fires the selectedResultSet() handler, which calls _createResultsFeatureLayer.
  • The results get loaded into a tab in the AttributeTable.
  • Click on a different result item in the tree.  The FeatureLayer with the results from the previously selected item is removed from the map. NOTE:  In our full application we only show one set of results on the map and in the attribute table at a time. The same process as above executes for the newly selected results item, and the results are successfully displayed in the AttributeTable.
  • Click on the originally selected results item in the tree and the same process executes again.
  • This time the circular reference exception gets thrown in the _createResultsFeatureLayer() function when calling the FeatureLayer constructor.

Any feedback, thoughts, or suggestions would be greatly appreciated.

Thank you in advance!

Gary

0 Kudos
1 Solution

Accepted Solutions
GarySinner
New Contributor III

The solution to my issue was to create copies of the features found by the query, and then use the set of copied features when creating the feature layer.  One of Kelly Hutchins' posts put me on the right track (thank you Kelly!).

The following bold lines in the following code snippet show the changes I made to the _createResultsFeatureLayer function in the code attached to the original post.

        _createResultsFeatureLayer: function (selectedResultsLayerItem) {

                //--- Kelly Hutchins forum post with example creating feature layer with layer definition:

                //---  https://community.esri.com/thread/99683

                // AVOID CIRCULAR REFERENCE EXCEPTION IN FeatureLayer CONSTRUCTOR BY MAKING

                // COPIES OF THE RESULTS, SPECIFICALLY COPIES OF THE RESULT GRAPHIC OBJECTS.

                // BASED ON ANOTHER POST FROM KELLY WITH WORKAROUND FOR A CIRCULAR

                // REFERENCE ISSUE WHEN PRINTING:

                // https://community.esri.com/message/70485#70485

                // THIS APPROACH WORKS.  THANK YOU KELLY! 

                // use toJson() to create an independent COPY of each result feature/graphic.

                // ONLY replacing the result's set of features, leaving all other properties of the

                // original results object intact.

                // MAKING *COPIES* OF THE ORIGINAL FEATURES IS THE KEY

                // TO AVOIDING THE CIRCULAR REFERENCE EXCEPTION.

                var copyFeatures = dojo.map(selectedResultsLayerItem.results.features, function (feature) {

                    return new esri.Graphic(feature.toJson());

                });

                selectedResultsLayerItem.results.features = copyFeatures;

                var featureCollection = {

                    layerDefinition: selectedResultsLayerItem.layerDefinition,

                    featureSet: selectedResultsLayerItem.results

                };

                    var featureLayer = new FeatureLayer(featureCollection,

                        {

                            mode: FeatureLayer.MODE_ONDEMAND,

                            id: featureLayerId

                        });

View solution in original post

0 Kudos
1 Reply
GarySinner
New Contributor III

The solution to my issue was to create copies of the features found by the query, and then use the set of copied features when creating the feature layer.  One of Kelly Hutchins' posts put me on the right track (thank you Kelly!).

The following bold lines in the following code snippet show the changes I made to the _createResultsFeatureLayer function in the code attached to the original post.

        _createResultsFeatureLayer: function (selectedResultsLayerItem) {

                //--- Kelly Hutchins forum post with example creating feature layer with layer definition:

                //---  https://community.esri.com/thread/99683

                // AVOID CIRCULAR REFERENCE EXCEPTION IN FeatureLayer CONSTRUCTOR BY MAKING

                // COPIES OF THE RESULTS, SPECIFICALLY COPIES OF THE RESULT GRAPHIC OBJECTS.

                // BASED ON ANOTHER POST FROM KELLY WITH WORKAROUND FOR A CIRCULAR

                // REFERENCE ISSUE WHEN PRINTING:

                // https://community.esri.com/message/70485#70485

                // THIS APPROACH WORKS.  THANK YOU KELLY! 

                // use toJson() to create an independent COPY of each result feature/graphic.

                // ONLY replacing the result's set of features, leaving all other properties of the

                // original results object intact.

                // MAKING *COPIES* OF THE ORIGINAL FEATURES IS THE KEY

                // TO AVOIDING THE CIRCULAR REFERENCE EXCEPTION.

                var copyFeatures = dojo.map(selectedResultsLayerItem.results.features, function (feature) {

                    return new esri.Graphic(feature.toJson());

                });

                selectedResultsLayerItem.results.features = copyFeatures;

                var featureCollection = {

                    layerDefinition: selectedResultsLayerItem.layerDefinition,

                    featureSet: selectedResultsLayerItem.results

                };

                    var featureLayer = new FeatureLayer(featureCollection,

                        {

                            mode: FeatureLayer.MODE_ONDEMAND,

                            id: featureLayerId

                        });

0 Kudos