Uncaught TypeError: Converting circular structure to JSON for printing

5459
9
Jump to solution
05-12-2015 02:47 PM
jamesa
by
New Contributor III

I want to print a map after buffer is completed and show all the highlighted parcels using print widget but I got error message:

Uncaught TypeError: Converting circular structure to JSON

The main code for buffer from here:https://community.esri.com/thread/121140?q=buffer%20results#463851

and use print widget from sample here: https://developers.arcgis.com/javascript/jssamples/widget_print_esri_request.html

Besides that, I also found this thread if you have graphics:

https://community.esri.com/thread/69239
with this solution  
var graphic = new esri.Graphic(result.feature.toJson());

But how do you apply it with FeatureLayer or geometry?

Please share you options.

Thank you.

0 Kudos
1 Solution

Accepted Solutions
RobertScheitlin__GISP
MVP Emeritus

James,

  Sure try this one:

View solution in original post

9 Replies
RobertScheitlin__GISP
MVP Emeritus

James,

   Can you zip up and attach your whole code?

0 Kudos
jamesa
by
New Contributor III

All my map services are secured services and not open to public.  When I first click on print button without any search,  I able to print a map . But after performed selected search with buffer or without buffer and text search with buffer will got error message,  For text search part, I added  this line " var graphic = new esri.Graphic(result.feature.toJson());" , so able to print.

I am not sure how to upload the zip file here.  So put the codes together below:

Can you help me take a look and  try to use your own map services, proxy server, &  print task to see if you got those error message?

Thank you for your time.

<!DOCTYPE html>

    <html>

    

    <head>

      <meta http-equiv="Content-Type" content="text/html; charset=utf-8">

      <!--The viewport meta tag is used to improve the presentation and behavior of the samples

      on iOS devices-->

      <meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no">

      <title>Buffer</title>

    

      <link rel="stylesheet" href="http://js.arcgis.com/3.13/dijit/themes/claro/claro.css">

      <link rel="stylesheet" href="http://js.arcgis.com/3.13/esri/css/esri.css">

      <style>

        html,

        body {

          height: 100%;

          width: 100%;

          margin: 0;

          padding: 0;

          overflow: hidden;

        }

        

        #leftPane {

          color: #000;

          width: 250px;

          padding-bottom: 15px;

        }

        

        #map {

          padding: 0;

        }

        

        .details {

          font-size: 14px;

          font-weight: 600;

          padding-bottom: 20px;

        }

        

        button {

          margin: 2px;

          cursor: pointer;

        }

      </style>

    

      <script src="http://js.arcgis.com/3.13/"></script>

      <script>

        require([

              "esri/map",

              "esri/config", "esri/layers/ArcGISDynamicMapServiceLayer",

              "esri/layers/FeatureLayer", "esri/dijit/Print", "esri/tasks/PrintTemplate", "esri/request",

   "esri/tasks/FindTask",

   "esri/tasks/FindParameters",

              "esri/symbols/SimpleFillSymbol",              

   "esri/symbols/SimpleLineSymbol",

              "dojo/request/iframe",  

   "esri/toolbars/draw",

   "esri/tasks/QueryTask",

              "esri/tasks/query", 

              "esri/graphic",

              "esri/graphicsUtils",

   "esri/geometry/Geometry",

   "esri/geometry/Extent",

              "esri/SpatialReference",

              "esri/geometry/geometryEngineAsync",

              "esri/tasks/GeometryService",

              "esri/Color",

              "dojo/on",

              "dojo/dom",

              "dijit/registry",

              "dojo/_base/array",

              "dojox/grid/DataGrid",

              "dojo/data/ItemFileReadStore",

              "dijit/form/Button",

              "dojo/parser",

   "dojo/store/Memory",

              "dojo/data/ItemFileWriteStore",

              "dgrid/OnDemandGrid",

              "dojox/grid/EnhancedGrid",

              "dojox/grid/enhanced/plugins/exporter/CSVWriter",

              "dojox/grid/enhanced/plugins/Printer",

              "dijit/layout/BorderContainer",

              "dijit/layout/ContentPane",

              "dojo/domReady!"

        ], function (

          Map, esriConfig, ArcGISDynamicMapServiceLayer, FeatureLayer, Print, PrintTemplate, esriRequest, FindTask, FindParameters, SimpleFillSymbol, SimpleLineSymbol, iframe, Draw, QueryTask, Query,

          Graphic, graphicsUtils, Geometry, Extent, SpatialReference, geometryEngineAsync, GeometryService,

          Color, on, dom, registry, arrayUtils, DataGrid, ItemFileReadStore, Button, parser, Memory,

          ItemFileWriteStore, Grid, EnhancedGrid, CSVWriter, Printer) {

          var map, center, zoom;

          var graphic;

          var bufferGra;

          var symbol, sfs, symbolP;

          var bufferGraF;

          var selectionToolbar;

          parser.parse();

         var printUrl = "http://servername/ags/rest/services/PrintCustom/ExportWebMapSecure3/GPServer/Export%20Web%20Map";

  var initExtent = new esri.geometry.Extent({"xmin":,"ymin":,"xmax":,"ymax":,"spatialReference":{"wkid":}});

   esri.config.defaults.io.proxyUrl = "http://servername/proxy/proxy.ashx";

       esri.config.defaults.io.alwaysUseProxy = true;

 

          map = new Map("map",{

   extent:initExtent

  });

          map.on("load", initSelectToolbar);

   on(dom.byId("selectFieldsButton"), "click", function () {

          selectionToolbar.activate(Draw.EXTENT);

        });

   var parcelsURL1 = "http://servername/ags/rest/services/Intranet/MapServer";

  map.addLayer(new ArcGISDynamicMapServiceLayer(parcelsURL1,

   { opacity: .95 }));

 

  // get print templates from the export web map task ----------------------

        var printInfo = esriRequest({

          "url": printUrl,

          "content": { "f": "json" }

        });

        printInfo.then(handlePrintInfo, handleError);

        function handlePrintInfo(resp) {

          var layoutTemplate, templateNames, mapOnlyIndex, templates;

          layoutTemplate = arrayUtils.filter(resp.parameters, function(param, idx) {

            return param.name === "Layout_Template";

          });

        

          if ( layoutTemplate.length == 0 ) {

            console.log("print service parameters name for templates must be \"Layout_Template\"");

            return;

          }

          templateNames = layoutTemplate[0].choiceList;

          // remove the MAP_ONLY template then add it to the end of the list of templates

          mapOnlyIndex = arrayUtils.indexOf(templateNames, "MAP_ONLY");

          if ( mapOnlyIndex > -1 ) {

            var mapOnly = templateNames.splice(mapOnlyIndex, mapOnlyIndex + 1)[0];

            templateNames.push(mapOnly);

          }

        

          // create a print template for each choice

          templates = arrayUtils.map(templateNames, function(ch) {

            var plate = new PrintTemplate();

            plate.layout = plate.label = ch;

            plate.format = "PDF";

            plate.layoutOptions = {

              "authorText": "Made by:  Esri's JS API Team",

              "copyrightText": "<copyright info here>",

              "legendLayers": [],

              "titleText": "Pool Permits",

              "scalebarUnit": "Miles"

            };

            return plate;

          });

          // create the print dijit

          printer = new Print({

            "map": map,

            "templates": templates,

            url: printUrl

          }, dom.byId("print_button"));

          printer.startup();

        }

        function handleError(err) {

          console.log("Something broke: ", err);

        }

 

//End Print Task --------------------------------------------

          registry.byId("search").on("click", doFind);

          registry.byId("applyBufferPF").on("click", doBuffer);

          registry.byId("applyBufferPSel").on("click", applyBufferPSel);

          registry.byId("clearParcelGrid").on("click", clearParcelGrid);          

//set symbol --------------

         symbol = new SimpleFillSymbol(SimpleFillSymbol.STYLE_NULL, new SimpleLineSymbol(SimpleFillSymbol.STYLE_SOLID, new Color([100, 100, 100]), 2), new Color([0, 0, 255, 0.20]));  //Gray line

  sfs = new SimpleFillSymbol(

            SimpleFillSymbol.STYLE_SOLID,

            new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID, new Color([98, 194, 204]), 2),

            new Color([98, 194, 204, 0.3])

          ); // blue solid

 

  symbolP = new SimpleFillSymbol(SimpleFillSymbol.STYLE_NONE,

  new SimpleLineSymbol(SimpleLineSymbol.STYLE_CROSS, new Color([98, 194, 204]), 2),

  new Color([98, 194, 204, 0.5])); // symbol for buffer result ring - black solid

 

//Find Parcel -----------

          //Create Find Task using the URL of the map service to search

          findTask = new FindTask("http://servername/ags/rest/services/Intranet/MapServer/");

 

   var parcelUrl = "http://servername/ags/rest/services/Intranet/MapServer/12";

          var featureLayerParcel = new FeatureLayer(parcelUrl, {

            mode: FeatureLayer.MODE_SELECTION,

            visible: true,

            outFields: ["*"]

          });

          featureLayerParcel.setSelectionSymbol(symbolP);

          map.addLayer(featureLayerParcel);

  map.on("load", function () {

              //Create the find parameters

              findParams = new FindParameters();

              findParams.returnGeometry = true;

              findParams.layerIds = [12];

              findParams.searchFields = ["parcelid"];

              findParams.outSpatialReference = map.spatialReference;

          });

          function doFind() {

   clearParcelGrid();

              //Set the search text to the value in the box

              findParams.searchText = dom.byId("Number").value;

              findTask.execute(findParams, function (results) {

      showResults(results);

              });

          }

            function showResults(results) {

              //This function works with an array of FindResult that the task returns

              map.graphics.clear();

              //create array of attributes

              var items = arrayUtils.map(results, function (result) {

                  //var graphic = result.feature;

                  var graphic = new esri.Graphic(result.feature.toJson());

   graphic.setSymbol(symbol);

                  map.graphics.add(graphic);

                  return result.feature.attributes;

              });

              //Create data object to be used in store

              var data = {

                  identifier: "parcelid", //This field needs to have unique values

                  label: "parcelid", //Name field for display. Not pertinent to a grid but may be used elsewhere.

                  items: items

              };

              //Create data store and bind to grid.

              var store = new ItemFileReadStore({

                  data: data

              });

              var gridP = registry.byId("gridP");

              gridP.setStore(store);

  var extent = esri.graphicsExtent(map.graphics.graphics);

       map.setExtent(extent, true);

   bufferGraF = map.graphics.graphics; // send graphic to buffer

          }

 

    function doBuffer(results) {

  var graphics = bufferGraF;

  var selectedGeoms = graphicsUtils.getGeometries(graphics);

            var symbol = new SimpleFillSymbol(SimpleFillSymbol.STYLE_SOLID, SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID,

                new Color([0, 0, 255, 0.65]), 2

              ),

              new Color([0, 0, 255, 0.35])

            );

            geometryEngineAsync.buffer(selectedGeoms, [100], GeometryService.UNIT_FOOT, true).then(

              function (geoms) {

                arrayUtils.forEach(geoms, function (geometry) {

                  map.graphics.add(new Graphic(geometry, symbol));

                });

                bufferGra = geoms;

                intersectParcelsF(); // combine buffer & intersect parcels

              }

            );

          }

 

  

 

    //query Parcel  

          function intersectParcelsF() {

            geometryEngineAsync.union(bufferGra).then(

              function (union) {

                var queryNew = new Query();

                queryNew.outFields = ["parcelid"];

                queryNew.spatialRelationship = Query.SPATIAL_REL_INTERSECTS;

                queryNew.geometry = union;

                queryNew.returnGeometry = true;

                featureLayerParcel.selectFeatures(queryNew, FeatureLayer.SELECTION_ADD, function (features, selectionMethod) {

                  var items = dojo.map(features, function (feature) {

                    return feature.attributes;

                  });

                  var data = {

                    identifier: "parcelid",

                    items: items

                  };

                  var store = new ItemFileReadStore({

                    data: data

                  });

                  var grid = registry.byId("parcelGrid");  

                  grid.setStore(store);

                  symbolInt = new SimpleFillSymbol(SimpleFillSymbol.STYLE_NULL, new SimpleLineSymbol(SimpleFillSymbol.STYLE_NULL, new Color([100, 100, 100]), 2), new Color([0, 0, 255, 0.20]));  //Gray line

                  arrayUtils.forEach(features, function (feature) {

                    graphic = new Graphic(feature.geometry, symbolInt);

                    map.graphics.add(graphic);

                  });

                });

              }

            );  

          }

 

 

 

     //End Find Parcel ---------------

 

//Select parcel -------------------------

 

  function initSelectToolbar (event) {

      map.graphics.clear();

   selectionToolbar = new Draw(event.map);

    var query2 = new esri.tasks.Query();

   on(selectionToolbar, "DrawEnd", function (geometry) {

  selectionToolbar.deactivate();

  query2.geometry = geometry;

  featureLayerP.selectFeatures(query2, esri.layers.FeatureLayer.SELECTION_NEW, function(features, selectionMethod) {

  var items30 = dojo.map(features, function(feature) {

  return feature.attributes;

  });

  var data30 = {

  identifier: "parcelid",

  items: items30

  };

  var store30 = new dojo.data.ItemFileReadStore({

  data: data30

  });

  var selGrid = registry.byId("gridP");

  selGrid.setStore(store30);

  selGrid.resize();

  map.setExtent(graphicsUtils.graphicsExtent(featureLayerP.getSelectedFeatures()), true);

  });

   });

  }

 

 

         var featureLayerUrl = "http://servername/ags/rest/services/Intranet/MapServer/12";

         var featureLayerP = new esri.layers.FeatureLayer(featureLayerUrl, {

             mode: esri.layers.FeatureLayer.MODE_SELECTION,

             visible: true,

  outFields: ["*"]

         });

  featureLayerP.setSelectionSymbol(symbolP);

         map.addLayer(featureLayerP);

       

 

 

//Select Parcel

    function intersectParcelsSel() {

            geometryEngineAsync.union(bufferGra).then(

              function (union) {

                var queryNew = new Query();

                queryNew.outFields = ["parcelid"];

                queryNew.spatialRelationship = Query.SPATIAL_REL_INTERSECTS;

                queryNew.geometry = union;

                queryNew.returnGeometry = true;

                featureLayerP.selectFeatures(queryNew, FeatureLayer.SELECTION_ADD, function (features, selectionMethod) {

                  var items = dojo.map(features, function (feature) {

                    return feature.attributes;

                  });

                  var data = {

                    identifier: "parcelid",

                    items: items

                  };

                  var store = new ItemFileReadStore({

                    data: data

                  });

                  var grid = registry.byId("parcelGrid");  

                  grid.setStore(store);

                  symbolInt = new SimpleFillSymbol(SimpleFillSymbol.STYLE_NULL, new SimpleLineSymbol(SimpleFillSymbol.STYLE_NULL, new Color([100, 100, 100]), 2), new Color([0, 0, 255, 0.20]));  //Gray line

                  arrayUtils.forEach(features, function (feature) {

                    graphic = new Graphic(feature.geometry, symbolInt);

                    map.graphics.add(graphic);

                  });

                });

              }

            );

          }  

      function applyBufferPSel() {

  alert(featureLayerP.graphics.length);

           //Select Parcel

  var graphicsSel = featureLayerP.graphics;

            var selectedGeomsSel = graphicsUtils.getGeometries(graphicsSel);

            var symbol = new SimpleFillSymbol(SimpleFillSymbol.STYLE_SOLID, SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID,

                new Color([0, 0, 255, 0.65]), 2

              ),

              new Color([0, 0, 255, 0.35])

            );

            geometryEngineAsync.buffer(selectedGeomsSel, [100], GeometryService.UNIT_FOOT, true).then(

              function (geoms) {

                arrayUtils.forEach(geoms, function (geometry) {

                  map.graphics.add(new Graphic(geometry, symbol));

                });

                bufferGra = geoms;

                intersectParcelsSel(); // combine buffer & intersect parcels

              }  

            );

          }

//End Select Parcel #2 -------------------------------------------------------------------------------------------------  

          function clearParcelGrid() {

            var newStore = new ItemFileReadStore({

              data: {

                idenitifer: "",

                items: []

              }

            });

            var grid = registry.byId("gridP");

            grid.setStore(newStore);

  var gridParcel = registry.byId("parcelGrid");

            gridParcel.setStore(newStore); 

  featureLayerParcel.clearSelection();

  featureLayerP.clearSelection();

            map.graphics.clear();

          }

        });

      </script>

    

      <body class="claro">

        <div data-dojo-type="dijit/layout/BorderContainer" data-dojo-props="design:'headline'" style="width:100%;height:100%;margin:0;">

          <div data-dojo-type="dijit/layout/ContentPane" data-dojo-props="region:'top'" style="height:200px;" title="Search">

            Search by Parcel #:

            <input type="text" id="Number" size="60"/>

            <button id="search" data-dojo-type="dijit.form.Button" type="button" data-dojo-attach-point="button">Search</button>

  <button id="applyBufferPF" data-dojo-type="dijit/form/Button" type="button" data-dojo-attach-point="button">Buffer</button>

  <br>

            <button id="selectFieldsButton" data-dojo-type="dijit/form/Button">Select Fields</button>

            <button id="applyBufferPSel" data-dojo-type="dijit/form/Button" type="button" data-dojo-attach-point="button">Buffer by Selected Parcel</button>

    <button id="clearParcelGrid" data-dojo-type="dijit/form/Button" type="button" data-dojo-attach-point="button">Clear</button>

           <div id="print_button"></div> 

            <table data-dojo-type="dojox/grid/EnhancedGrid" data-dojo-id="gridP" id="gridP" data-dojo-props="rowsPerPage:'5', rowSelector:'20px', plugins:{printer: true, exporter: true}">

              <thead>               

    <tr>

   <th field="parcelid">Parcel ID</th>

                </tr>

              </thead>

            </table>

  <br>

            <table data-dojo-type="dojox/grid/EnhancedGrid" data-dojo-id="parcelGrid" id="parcelGrid" data-dojo-props="rowsPerPage:'5', rowSelector:'20px', plugins:{printer: true, exporter: true}">   

                <thead>

                  <tr>

  <th field="parcelid">Parcel ID</th>

                  </tr>

                </thead>

           </table>

          </div> 

          <div id="map" data-dojo-props="region:'center'" data-dojo-type="dijit/layout/ContentPane" style="border:1px solid #000;"></div>

        </div>

      </body>

0 Kudos
RobertScheitlin__GISP
MVP Emeritus

James,

  I switched all your use of FeatureLayer to instead use GraphicsLayer. This allowed be to get past the Cyclic error.

0 Kudos
jamesa
by
New Contributor III

Robert,

Thank you for your attachment file.  Now I only got same error message for printing when try to do a text search with buffer.  Do I also need to use GraphicsLayer inside showResults function instead of map.graphics.add(graphic)?

Thank you again.

0 Kudos
RobertScheitlin__GISP
MVP Emeritus

James,

  So it turns out the real issue was with the main parcel that was selected before the buffer needed to be removed to prevent a duplicate of itself from being present in the print.  I have reverted much of my previous changes and tested this pretty thoroughly. I made some other changes too.

0 Kudos
jamesa
by
New Contributor III

I comment out this line //findParams.contains = false; then able to run a text search and everything working great! Is there possible to make buffer ring on top of parcels? Didn't find it under API reference for GraphicsLayer.

Thank you Robert so much for your time.

0 Kudos
RobertScheitlin__GISP
MVP Emeritus

James,

  Sure try this one:

jamesa
by
New Contributor III

Thank you so much.  It works. Can I ask you last questions before I mark this thread or I need to open a new thread.  Not sure. I try to add some functions inside showResults() to can zoom to selected parcels on datagrid record, mouseover to highlight parcel or mouseout.  I didn't find any error message when adding those functions.  Thanks again.

gridP.on("rowclick", onRowClickHandler);

gridP.on("mouseover", onMouseOverHandler);

gridP.on("mouseout", onMouseOutHandler);

function onRowClickHandler(evt) {

          var clickedTaxLotId = evt.grid.getItem(evt.rowIndex).parcelid;

          var selectedTaxLot = arrayUtils.filter(parcelGL.graphics, function (graphic) {

            return ((graphic.attributes) && graphic.attributes.parcelid === clickedTaxLotId);

          });

          if ( selectedTaxLot.length ) {

            map.setExtent(selectedTaxLot[0].geometry.getExtent(), true);

          }

        }

  function onMouseOverHandler(evt){

    if(evt.rowIndex == -1){

  return;

  }

              var grid = registry.byId("gridP");

  var rowId = grid.getItem(evt.rowIndex).parcelid;

  arrayUtils.some(parcelGL.graphics,function(graphic){

    if ((graphic.attributes) && graphic.attributes.parcelid === rowId) {

    graphic.setSymbol(sfs);

  return true;

  }

  }); 

  }

  function onMouseOutHandler(evt){

  arrayUtils.some(parcelGL.graphics,function(graphic){

  if (graphic.symbol == sfs) {

  graphic.setSymbol(symbolP);

  return true;

  }

  }); 

  };

0 Kudos
RobertScheitlin__GISP
MVP Emeritus

James,

   You definitely need to close this thread by marking it as answered. Your problem is

I try to add some functions inside showResults()

Don't add those "on" event in the showResults() function just add them right after your other event handlers right after:

registry.byId("clearBuffer").on("click", clearBuffer);

0 Kudos