{"id":307942,"date":"2018-09-04T08:00:09","date_gmt":"2018-09-04T15:00:09","guid":{"rendered":"http:\/\/www.esri.com\/arcgis-blog\/?post_type=blog&#038;p=307942"},"modified":"2018-08-31T12:48:12","modified_gmt":"2018-08-31T19:48:12","slug":"explore-data-in-dynamic-workspaces-with-smart-mapping","status":"publish","type":"blog","link":"https:\/\/www.esri.com\/arcgis-blog\/products\/js-api-arcgis\/mapping\/explore-data-in-dynamic-workspaces-with-smart-mapping","title":{"rendered":"Build web apps for exploring data in dynamic workspaces"},"author":6561,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","format":"standard","meta":{"_acf_changed":false,"_searchwp_excluded":""},"categories":[22941],"tags":[30111,30801,27491,24581],"industry":[],"product":[36831,36601],"class_list":["post-307942","blog","type-blog","status-publish","format-standard","hentry","category-mapping","tag-data-visualization","tag-dynamic-layers","tag-jsapi4","tag-smart-mapping","product-js-api-arcgis","product-developers"],"acf":{"short_description":"With Smart Mapping, you can build data exploration web apps for layers created from dynamic workspaces.","flexible_content":[{"acf_fc_layout":"content","content":"<p>A lesser-known, but powerful, feature of the ArcGIS API for JavaScript (JS API) is the ability to create dynamic <a href=\"https:\/\/www.esri.com\/arcgis-blog\/products\/js-api-arcgis\/mapping\/whats-the-deal-with-mapimagelayer\/\">MapImageLayer<\/a> sublayers from data in <a href=\"https:\/\/enterprise.arcgis.com\/en\/server\/latest\/publish-services\/windows\/about-dynamic-layers.htm\">dynamic workspaces<\/a>.<\/p>\n<p>A while ago, <a href=\"https:\/\/www.esri.com\/arcgis-blog\/products\/js-api-arcgis\/mapping\/smart-mapping-with-dynamic-workspaces\/\">I wrote about how you can generate data-driven visualization styles<\/a> for dynamic layers using the 3.x series of the JS API. As of version 4.7 of the JS API, you can now generate these visualizations with more intuitive, readable code. This post will demonstrate how to create <a href=\"https:\/\/ekenes.github.io\/esri-js-samples\/smart-mapping\/dynamic-layer-join.html\">this 3.x JS API web app<\/a> with TypeScript using the ArcGIS API 4.8 for JavaScript.<\/p>\n"},{"acf_fc_layout":"storymap","title":"","description":"","static":false,"storymap_url":"<a href=\"https:\/\/ekenes.github.io\/esri-ts-samples\/visualization\/smart-mapping\/dynamic-layers\/\">https:\/\/ekenes.github.io\/esri-ts-samples\/visualization\/smart-mapping\/dynamic-layers\/<\/a>"},{"acf_fc_layout":"content","content":"<p>This sample allows you to explore ancestry data in the United States. It demonstrates how to do the following:<\/p>\n<p>1. Join a non-spatial table with ancestry data from a dynamic workspace to a layer with geometries representing U.S. states<\/p>\n<p>2. Generate a meaningful visualization of the joined attributes using a Smart Mapping renderer creator method<\/p>\n<p>This is doable with the 3.x JS API as seen in the <a href=\"https:\/\/ekenes.github.io\/esri-js-samples\/smart-mapping\/dynamic-layer-join.html\">original app<\/a>, but is a little inelegant and cumbersome. The 4.x JS API makes the workflow for creating this app simpler thanks to the following:<\/p>\n<ul>\n<li>Autocasting<\/li>\n<li>A helper method for creating a FeatureLayer directly from a MapImageLayer Sublayer<\/li>\n<li>Support for generating renderers with Arcade expressions<\/li>\n<li>Simplified APIs for updating a Sublayer&#8217;s renderer and popup<\/li>\n<\/ul>\n<h2>Autocasting<\/h2>\n<p><a href=\"https:\/\/www.esri.com\/arcgis-blog\/products\/js-api-arcgis\/uncategorized\/speed-up-your-javascript-development-with-autocasting\/\">Autocasting<\/a> eases the coding workflow by automatically importing necessary modules. The 3.x app requires manually adding <a href=\"https:\/\/github.com\/ekenes\/esri-js-samples\/blob\/master\/smart-mapping\/dynamic-layer-join.html#L60-L76\">17 module imports<\/a>. The 4.x version of the app only <a href=\"https:\/\/github.com\/ekenes\/esri-ts-samples\/blob\/master\/visualization\/smart-mapping\/dynamic-layers\/app\/main.ts#L3-L8\">requires manually adding five module imports<\/a>.<\/p>\n<p>Constructing the joined dynamic layer in 3.x involves <a href=\"https:\/\/github.com\/ekenes\/esri-js-samples\/blob\/master\/smart-mapping\/dynamic-layer-join.html#L103-L195\">~80 lines of code<\/a>, but can now be done in about 25 lines using 4.x.<\/p>\n<pre><code\r\n style=\"display: block; overflow-x: auto; padding: 0.5em; color: #333; background: #f8f8f8; -webkit-text-size-adjust: none;\">\r\n<span\r\n style=\"color: #333; font-weight: bold;\">const<\/span> layer = <span\r\n style=\"color: #333; font-weight: bold;\">new<\/span> MapImageLayer({\r\n  url: <span\r\n style=\"color: #d14;\">\"https:\/\/sampleserver6.arcgisonline.com\/arcgis\/rest\/services\/AGP\/Census\/MapServer\"<\/span>,\r\n  title: <span\r\n style=\"color: #d14;\">\"United States Population\"<\/span>,\r\n  listMode: <span\r\n style=\"color: #d14;\">\"hide-children\"<\/span>,\r\n  sublayers: [{\r\n    title: <span\r\n style=\"color: #d14;\">\"% population with selected ancestry\"<\/span>,\r\n    id: <span\r\n style=\"color: #008080;\">0<\/span>,\r\n    opacity: <span\r\n style=\"color: #008080;\">0.75<\/span>,\r\n    source: {\r\n      dataSource: {\r\n        leftTableSource: {\r\n          mapLayerId: <span\r\n style=\"color: #008080;\">3<\/span>  <span\r\n style=\"color: #998; font-style: italic;\">\/\/ states sublayer<\/span>\r\n        },\r\n        rightTableSource: {\r\n          dataSource: {\r\n            workspaceId: <span\r\n style=\"color: #d14;\">\"CensusFileGDBWorkspaceID\"<\/span>,\r\n            dataSourceName: <span\r\n style=\"color: #d14;\">\"ancestry\"<\/span>  <span\r\n style=\"color: #998; font-style: italic;\">\/\/ non-spatial table<\/span>\r\n          }\r\n        },\r\n        leftTableKey: <span\r\n style=\"color: #d14;\">\"STATE_NAME\"<\/span>,\r\n        rightTableKey: <span\r\n style=\"color: #d14;\">\"State\"<\/span>,\r\n        joinType: <span\r\n style=\"color: #d14;\">\"left-outer-join\"<\/span>\r\n      }\r\n    }\r\n  }] <span\r\n style=\"color: #333; font-weight: bold;\">as<\/span> esri.Sublayer[]\r\n});\r\n<\/code><\/pre>\n<p>Notice you don&#8217;t even need to specify which type of dynamic layer sources you need for each side of the join. The API figures it out for you.<\/p>\n<h2>Create a FeatureLayer with a dynamic source directly from a Sublayer<\/h2>\n<p>Starting at version 4.7, you can create a FeatureLayer with a dynamic source directly from a Sublayer. This is done with the <a href=\"https:\/\/developers.arcgis.com\/javascript\/latest\/api-reference\/esri-layers-support-Sublayer.html#createFeatureLayer\">createFeatureLayer()<\/a> method on the Sublayer class.<\/p>\n<p>In 3.x, you have to construct a new FeatureLayer, referencing the <code>dynamicLayer<\/code> endpoint in the URL, and set the same source you created for the Sublayer in the constructor options.<\/p>\n<pre><code\r\n style=\"display: block; overflow-x: auto; padding: 0.5em; color: #333; background: #f8f8f8; -webkit-text-size-adjust: none;\">\r\n<span\r\n style=\"color: #333; font-weight: bold;\">var<\/span> layerOptions = {\r\n  mode: FeatureLayer.MODE_SELECTION,\r\n  outFields: [<span\r\n style=\"color: #d14;\">\"*\"<\/span>],\r\n  source: dynamicLayerDataSource\r\n};\r\nfeatureLayer = <span\r\n style=\"color: #333; font-weight: bold;\">new<\/span> FeatureLayer(layerUrl + <span\r\n style=\"color: #d14;\">\"\/dynamicLayer\"<\/span>, layerOptions);\r\n<\/code><\/pre>\n<p>In 4.x, you simply call the <code>createFeatureLayer()<\/code> helper method.<\/p>\n<pre><code\r\n style=\"display: block; overflow-x: auto; padding: 0.5em; color: #333; background: #f8f8f8; -webkit-text-size-adjust: none;\">\r\n<span\r\n style=\"color: #333; font-weight: bold;\">const<\/span> ancestrySublayer = layer.sublayers.find(<span\r\n><span\r\n style=\"color: #333; font-weight: bold;\">function<\/span>(<span\r\n>sublayer: esri.Sublayer<\/span>) <\/span>{\r\n  <span\r\n style=\"color: #333; font-weight: bold;\">return<\/span> sublayer.title === <span\r\n style=\"color: #d14;\">\"% population with selected ancestry\"<\/span>;\r\n});\r\n<span\r\n style=\"color: #333; font-weight: bold;\">const<\/span> ancestryFeatureLayer = ancestrySublayer.createFeatureLayer();\r\n<\/code><\/pre>\n<p>You can use a FeatureLayer instance to verify the join was successful by setting a breakpoint in your developer tools and checking the <code>fields<\/code> array on the layer.<\/p>\n"},{"acf_fc_layout":"image","image":{"ID":309082,"id":309082,"title":"show-joined-fields","filename":"show-joined-fields.gif","filesize":1686909,"url":"https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2018\/09\/show-joined-fields.gif","link":"https:\/\/www.esri.com\/arcgis-blog\/products\/js-api-arcgis\/mapping\/explore-data-in-dynamic-workspaces-with-smart-mapping\/show-joined-fields","alt":"","author":"6561","description":"","caption":"Fields in dynamic layers created from table joins will be prefixed by the table\/layer name of the original data source.","name":"show-joined-fields","status":"inherit","uploaded_to":307942,"date":"2018-08-28 20:47:23","modified":"2018-08-28 20:48:40","menu_order":0,"mime_type":"image\/gif","type":"image","subtype":"gif","icon":"https:\/\/www.esri.com\/arcgis-blog\/wp-includes\/images\/media\/default.png","width":480,"height":249,"sizes":{"thumbnail":"https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2018\/09\/show-joined-fields.gif","thumbnail-width":213,"thumbnail-height":110,"medium":"https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2018\/09\/show-joined-fields.gif","medium-width":464,"medium-height":241,"medium_large":"https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2018\/09\/show-joined-fields.gif","medium_large-width":480,"medium_large-height":249,"large":"https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2018\/09\/show-joined-fields.gif","large-width":480,"large-height":249,"1536x1536":"https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2018\/09\/show-joined-fields.gif","1536x1536-width":480,"1536x1536-height":249,"2048x2048":"https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2018\/09\/show-joined-fields.gif","2048x2048-width":480,"2048x2048-height":249,"card_image":"https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2018\/09\/show-joined-fields.gif","card_image-width":480,"card_image-height":249,"wide_image":"https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2018\/09\/show-joined-fields.gif","wide_image-width":480,"wide_image-height":249}},"image_position":"center","orientation":"horizontal","hyperlink":""},{"acf_fc_layout":"content","content":"<p>A FeatureLayer instance is required for this app because generating a renderer with a Smart Mapping method requires either a FeatureLayer, CSVLayer, or SceneLayer. However, the renderer generated from Smart Mapping can be applied back to a MapImageLayer sublayer.<\/p>\n<h2>Generate a renderer with Arcade<\/h2>\n<p>This app allows you to explore ancestry data in the United States, while demonstrating how different classification schemes can affect a visualization. To generate the appropriate renderer I use the <a href=\"https:\/\/developers.arcgis.com\/javascript\/latest\/api-reference\/esri-renderers-smartMapping-creators-color.html#createClassBreaksRenderer\">createClassBreaksRenderer()<\/a> method on the <a href=\"https:\/\/developers.arcgis.com\/javascript\/latest\/api-reference\/esri-renderers-smartMapping-creators-color.html\">colorRendererCreator<\/a> Smart Mapping module. <\/p>\n<p>All that&#8217;s needed for the renderer creator method is a basemap, a FeatureLayer, and a field name. You can optionally change the classification method, which I exposed as an option to the user for educational purposes. <\/p>\n"},{"acf_fc_layout":"image","image":{"ID":309222,"id":309222,"title":"classification","filename":"classification.gif","filesize":1646552,"url":"https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2018\/09\/classification.gif","link":"https:\/\/www.esri.com\/arcgis-blog\/products\/js-api-arcgis\/mapping\/explore-data-in-dynamic-workspaces-with-smart-mapping\/classification","alt":"","author":"6561","description":"","caption":"The classification theme vastly changes a class breaks visualization. The createClassedRenderer() Smart Mapping method allows you to choose different classification schemes for data exploration.","name":"classification","status":"inherit","uploaded_to":307942,"date":"2018-08-28 21:39:32","modified":"2018-08-28 21:41:23","menu_order":0,"mime_type":"image\/gif","type":"image","subtype":"gif","icon":"https:\/\/www.esri.com\/arcgis-blog\/wp-includes\/images\/media\/default.png","width":480,"height":299,"sizes":{"thumbnail":"https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2018\/09\/classification.gif","thumbnail-width":213,"thumbnail-height":133,"medium":"https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2018\/09\/classification.gif","medium-width":419,"medium-height":261,"medium_large":"https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2018\/09\/classification.gif","medium_large-width":480,"medium_large-height":299,"large":"https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2018\/09\/classification.gif","large-width":480,"large-height":299,"1536x1536":"https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2018\/09\/classification.gif","1536x1536-width":480,"1536x1536-height":299,"2048x2048":"https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2018\/09\/classification.gif","2048x2048-width":480,"2048x2048-height":299,"card_image":"https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2018\/09\/classification.gif","card_image-width":480,"card_image-height":299,"wide_image":"https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2018\/09\/classification.gif","wide_image-width":480,"wide_image-height":299}},"image_position":"center","orientation":"horizontal","hyperlink":""},{"acf_fc_layout":"content","content":"<p><a href=\"https:\/\/github.com\/ekenes\/esri-js-samples\/blob\/master\/smart-mapping\/dynamic-layer-join.html#L337-L344\">In the 3.x app<\/a>, the field selected by the user in the dropdown menu is passed to the field parameter and normalized by a total population field. This works for creating a good visualization, but it makes the legend look awkward since all values are ratios (values between 0 and 1). <a href=\"https:\/\/github.com\/ekenes\/esri-js-samples\/blob\/master\/smart-mapping\/dynamic-layer-join.html#L355-L359\">I added extra logic<\/a> to format the labels of the generated class breaks as percentages since it makes the legend easier to read and comprehend.<\/p>\n<p>Smart Mapping now supports <a href=\"https:\/\/developers.arcgis.com\/javascript\/latest\/guide\/arcade\/index.html\">Arcade expressions<\/a>, which means you can pass an expression that returns a number instead providing the name of a numeric field. In the 4.x version of the app, I use an Arcade expression for formatting the ancestry to population ratios as percentages. Now I don&#8217;t have to loop through the breaks and modify the labels later on in the app.<\/p>\n<pre><code\r\n style=\"display: block; overflow-x: auto; padding: 0.5em; color: #333; background: #f8f8f8; -webkit-text-size-adjust: none;\">\r\n<span\r\n style=\"color: #333; font-weight: bold;\">const<\/span> params = {\r\n  layer: ancestryFeatureLayer,\r\n  basemap: map.basemap,\r\n  valueExpression: <span\r\n style=\"color: #d14;\">`Round( ( $feature['<span\r\n style=\"color: #333; font-weight: normal;\">${ancestrySelect.value}<\/span>'] \/ $feature['states.POP2007'] ) * 100, 1);`<\/span>,\r\n  view: view,  <span\r\n style=\"color: #998; font-style: italic;\">\/\/ required with valueExpression<\/span>\r\n  classificationMethod: classSelect.value\r\n};\r\n\r\n<span\r\n style=\"color: #333; font-weight: bold;\">const<\/span> response = <span\r\n style=\"color: #333; font-weight: bold;\">await<\/span> colorRendererCreator.createClassBreaksRenderer(params);\r\n<\/code><\/pre>\n<p>Since this app is written with <a href=\"https:\/\/developers.arcgis.com\/javascript\/latest\/guide\/typescript-setup\/index.html\">Typescript<\/a>, you can take advantage of <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/JavaScript\/Reference\/Template_literals\">template literals<\/a> when constructing the Arcade expression used as the basis for the data-driven visualization. I also take advantage of <a href=\"https:\/\/javascript.info\/async-await\">async\/await<\/a> since it simplifies the structure of the code.<\/p>\n<h2>Update a Sublayer&#8217;s renderer and popup<\/h2>\n<p>Updating MapImageLayer sublayer properties in 4.x, such as the <a href=\"https:\/\/developers.arcgis.com\/javascript\/latest\/api-reference\/esri-layers-support-Sublayer.html#renderer\">renderer<\/a> and <a href=\"https:\/\/developers.arcgis.com\/javascript\/latest\/api-reference\/esri-layers-support-Sublayer.html#popupTemplate\">popupTemplate<\/a> is much improved. In 3.x you have to do the following just to update the renderer of one sublayer.<\/p>\n<pre><code\r\n style=\"display: block; overflow-x: auto; padding: 0.5em; color: #333; background: #f8f8f8; -webkit-text-size-adjust: none;\">\r\n<span\r\n style=\"color: #333; font-weight: bold;\">var<\/span> optionsArray = [];\r\n<span\r\n style=\"color: #998; font-style: italic;\">\/\/ Create a LayerDrawingOptions object used to set<\/span>\r\n<span\r\n style=\"color: #998; font-style: italic;\">\/\/ a renderer on a sublayer of a DynamicLayer<\/span>\r\n<span\r\n style=\"color: #333; font-weight: bold;\">var<\/span> drawingOptions = <span\r\n style=\"color: #333; font-weight: bold;\">new<\/span> LayerDrawingOptions();\r\n<span\r\n style=\"color: #998; font-style: italic;\">\/\/ Update label in legend for each break<\/span>\r\n<span\r\n style=\"color: #333; font-weight: bold;\">var<\/span> breaks = response.renderer.infos;\r\nbreaks.forEach(<span\r\n><span\r\n style=\"color: #333; font-weight: bold;\">function<\/span>(<span\r\n>breakInfo, i<\/span>)<\/span>{\r\n  <span\r\n style=\"color: #333; font-weight: bold;\">var<\/span> max = <span\r\n style=\"color: #0086b3;\">Math<\/span>.round(breakInfo.maxValue * <span\r\n style=\"color: #008080;\">1000<\/span>) \/ <span\r\n style=\"color: #008080;\">10<\/span>;\r\n  <span\r\n style=\"color: #333; font-weight: bold;\">var<\/span> min = <span\r\n style=\"color: #0086b3;\">Math<\/span>.round(breakInfo.minValue * <span\r\n style=\"color: #008080;\">1000<\/span>) \/ <span\r\n style=\"color: #008080;\">10<\/span>;\r\n  breakInfo.label = min + <span\r\n style=\"color: #d14;\">\"% - \"<\/span> + max + <span\r\n style=\"color: #d14;\">\"%\"<\/span>;\r\n});\r\n<span\r\n style=\"color: #998; font-style: italic;\">\/\/ Remove the default symbol so it doesn't display in the legend.<\/span>\r\n<span\r\n style=\"color: #333; font-weight: bold;\">delete<\/span> response.renderer[<span\r\n style=\"color: #d14;\">\"defaultSymbol\"<\/span>];\r\n<span\r\n style=\"color: #998; font-style: italic;\">\/\/ Set the response renderer on the drawing options<\/span>\r\ndrawingOptions.renderer = response.renderer;\r\n<span\r\n style=\"color: #998; font-style: italic;\">\/\/ And place the drawing options in index 3 so it applies to the states sublayer<\/span>\r\noptionsArray[<span\r\n style=\"color: #008080;\">3<\/span>] = drawingOptions;\r\n<span\r\n style=\"color: #998; font-style: italic;\">\/\/ set the renderer on the layer<\/span>\r\ncensusMapServiceLayer.setLayerDrawingOptions(optionsArray);\r\n<\/code><\/pre>\n<p>In 4.x, it takes just one line of code after waiting for the promise returned from the renderer creator to resolve.<\/p>\n<pre><code\r\n style=\"display: block; overflow-x: auto; padding: 0.5em; color: #333; background: #f8f8f8; -webkit-text-size-adjust: none;\">\r\n<span\r\n style=\"color: #333; font-weight: bold;\">const<\/span> response = <span\r\n style=\"color: #333; font-weight: bold;\">await<\/span> colorRendererCreator.createClassBreaksRenderer(params);\r\nancestrySublayer.renderer = response.renderer;\r\n<\/code><\/pre>\n<p>Updating the <code>popupTemplate<\/code> similarly is done by setting the <code>popupTemplate<\/code> property directly on the Sublayer instance.<\/p>\n<pre><code\r\n style=\"display: block; overflow-x: auto; padding: 0.5em; color: #333; background: #f8f8f8; -webkit-text-size-adjust: none;\">\r\nancestrySublayer.popupTemplate = {\r\n  title: <span\r\n style=\"color: #d14;\">\"{states.STATE_NAME}\"<\/span>,\r\n  content: <span\r\n style=\"color: #d14;\">`{ancestry.<span\r\n style=\"color: #333; font-weight: normal;\">${selectedAncestry}<\/span>} of the {states.POP2007} people \r\n    in {states.STATE_NAME} have <span\r\n style=\"color: #333; font-weight: normal;\">${selectedAncestry}<\/span> ancestry.`<\/span>,\r\n  expressionInfos: [{\r\n    name: <span\r\n style=\"color: #d14;\">\"per_ancestry\"<\/span>,\r\n    expression: response.renderer.valueExpression\r\n  }],\r\n  fieldInfos: [{\r\n    fieldName: <span\r\n style=\"color: #d14;\">\"states.POP2007\"<\/span>,\r\n    format: {\r\n      digitSeparator: <span\r\n style=\"color: #333; font-weight: 500;\">true<\/span>,\r\n      places: <span\r\n style=\"color: #008080;\">0<\/span>\r\n    }\r\n  }, {\r\n    fieldName: <span\r\n style=\"color: #d14;\">`ancestry.<span\r\n style=\"color: #333; font-weight: normal;\">${selectedAncestry}<\/span>`<\/span>,\r\n    format: {\r\n      digitSeparator: <span\r\n style=\"color: #333; font-weight: 500;\">true<\/span>,\r\n      places: <span\r\n style=\"color: #008080;\">0<\/span>\r\n    }\r\n  }]\r\n} <span\r\n style=\"color: #333; font-weight: bold;\">as<\/span> esri.PopupTemplate;\r\n<\/code><\/pre>\n<p>Once again, here&#8217;s the final app, along with the <a href=\"https:\/\/github.com\/ekenes\/esri-ts-samples\/tree\/master\/visualization\/smart-mapping\/dynamic-layers\">source code<\/a>.<\/p>\n"},{"acf_fc_layout":"storymap","title":"","description":"","static":false,"storymap_url":"<a href=\"https:\/\/ekenes.github.io\/esri-ts-samples\/visualization\/smart-mapping\/dynamic-layers\/\">https:\/\/ekenes.github.io\/esri-ts-samples\/visualization\/smart-mapping\/dynamic-layers\/<\/a>"},{"acf_fc_layout":"content","content":"<h2>Summary<\/h2>\n<p>The ArcGIS API for JavaScript version 4.7 or greater provides a better coding pattern for generating renderers for MapImageLayer sublayers. The same functionality works in 3D <a href=\"https:\/\/developers.arcgis.com\/javascript\/latest\/api-reference\/esri-views-SceneView.html\">SceneViews<\/a>. However, if you would like to take advantage of 3D symbology, you\u2019ll need to add the dynamic FeatureLayer instance to the map rather than the MapImageLayer since MapImageLayer doesn\u2019t support 3D symbology.<\/p>\n<p>A lot of what was discussed in this post assumes some prior knowledge of key concepts of MapImageLayer and Smart Mapping. To read more about these topics, I recommend the following:<\/p>\n<p>1. <a href=\"https:\/\/www.esri.com\/arcgis-blog\/products\/js-api-arcgis\/mapping\/whats-the-deal-with-mapimagelayer\/\">What&#8217;s the deal with MapImageLayer<\/a> \u2013 This blog provides a nice overview of how to use dynamic layers in web apps and how to set up a dynamic workspace on your server.<\/p>\n<p>2. <a href=\"https:\/\/www.esri.com\/arcgis-blog\/products\/js-api-arcgis\/mapping\/using-smart-mapping-in-custom-web-apps\/\">Using Smart Mapping in custom web apps<\/a> \u2013 I\u2019ve written a number of blogs on how to build data exploration apps with the smart mapping tools available in the JS API. Here&#8217;s one to get you started.<\/p>\n<p>3. <a href=\"https:\/\/www.esri.com\/arcgis-blog\/products\/js-api-arcgis\/mapping\/generate-arcade-expressions-for-data-exploration-web-apps\/\">Generate Arcade expressions for data exploration web apps<\/a> \u2013 If you\u2019re unfamiliar with Arcade, I encourage you to read this post about generating Arcade for use in data exploration web apps.<\/p>\n<p>The 4.x version of the sample app was written in <a href=\"https:\/\/www.typescriptlang.org\/\">Typescript<\/a>. If you are new to TypeScript, or developing web apps in TypeScript with the JS API, I encourage you to read <a href=\"https:\/\/www.esri.com\/arcgis-blog\/products\/js-api-arcgis\/mapping\/improved-typescript-development-with-arcgis-api-for-javascript\/?rmedium=redirect&#038;rsource=\/esri\/arcgis\/2017\/12\/14\/improved-typescript\">this blog<\/a> and <a href=\"https:\/\/developers.arcgis.com\/javascript\/latest\/guide\/typescript-setup\/index.html\">this guide<\/a>, which discuss the benefits of developing with TypeScript and help you with getting started. <\/p>\n<p>A <a href=\"https:\/\/developers.arcgis.com\/javascript\/latest\/sample-code\/visualization-sm-sublayer\/index.html\">non-Typescript version of this app<\/a> can also be explored in the ArcGIS API for JavaScript documentation.<\/p>\n"}],"authors":[{"ID":6561,"user_firstname":"Kristian","user_lastname":"Ekenes","nickname":"Kristian Ekenes","user_nicename":"kekenes","display_name":"Kristian Ekenes","user_email":"KEkenes@esri.com","user_url":"https:\/\/github.com\/ekenes","user_registered":"2018-03-02 00:18:32","user_description":"Kristian Ekenes is a Principal Product Engineer at Esri specializing in data visualization on the web. He works on the ArcGIS Maps SDK for JavaScript, ArcGIS Arcade, and Map Viewer in ArcGIS Online. Kristian's work focuses on researching and developing new and innovative data visualization capabilities of geospatial data in web maps, Arcade integration in web maps, and applications of generative AI assistants in web maps. Prior to joining Esri, he worked as a GIS Specialist for an environmental consulting company. Kristian has degrees from Brigham Young University and Arizona State University.","user_avatar":"<img data-del=\"avatar\" src='https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2021\/10\/ekenes-zurich-213x200.png' class='avatar pp-user-avatar avatar-96 photo ' height='96' width='96'\/>"}],"related_articles":[{"ID":72001,"post_author":"6561","post_date":"2016-05-25 06:00:32","post_date_gmt":"2016-05-25 06:00:32","post_content":"","post_title":"Smart Mapping with dynamic workspaces","post_excerpt":"","post_status":"publish","comment_status":"closed","ping_status":"closed","post_password":"","post_name":"smart-mapping-with-dynamic-workspaces","to_ping":"","pinged":"","post_modified":"2018-05-25 22:42:20","post_modified_gmt":"2018-05-25 22:42:20","post_content_filtered":"","post_parent":0,"guid":"http:\/\/www.esri.com\/arcgis-blog\/products\/product\/uncategorized\/smart-mapping-with-dynamic-workspaces\/","menu_order":0,"post_type":"blog","post_mime_type":"","comment_count":"0","filter":"raw"},{"ID":199072,"post_author":"6561","post_date":"2018-06-05 08:00:08","post_date_gmt":"2018-06-05 08:00:08","post_content":"","post_title":"Generate Arcade expressions for data exploration web apps","post_excerpt":"","post_status":"publish","comment_status":"closed","ping_status":"closed","post_password":"","post_name":"generate-arcade-expressions-for-data-exploration-web-apps","to_ping":"","pinged":"","post_modified":"2024-11-11 12:37:33","post_modified_gmt":"2024-11-11 20:37:33","post_content_filtered":"","post_parent":0,"guid":"http:\/\/www.esri.com\/arcgis-blog\/?post_type=blog&#038;p=199072","menu_order":0,"post_type":"blog","post_mime_type":"","comment_count":"0","filter":"raw"},{"ID":164041,"post_author":"7451","post_date":"2018-05-08 07:01:50","post_date_gmt":"2018-05-08 07:01:50","post_content":"","post_title":"What\u2019s the Deal with MapImageLayer?","post_excerpt":"","post_status":"publish","comment_status":"closed","ping_status":"closed","post_password":"","post_name":"whats-the-deal-with-mapimagelayer","to_ping":"","pinged":"","post_modified":"2018-05-08 16:37:03","post_modified_gmt":"2018-05-08 16:37:03","post_content_filtered":"","post_parent":0,"guid":"http:\/\/www.esri.com\/arcgis-blog\/?post_type=blog&#038;p=164041","menu_order":0,"post_type":"blog","post_mime_type":"","comment_count":"0","filter":"raw"}],"card_image":"https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2018\/09\/card.png","wide_image":"https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2018\/09\/wide-1.png"},"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v25.9 (Yoast SEO v25.9) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Build web apps for exploring data in dynamic workspaces<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.esri.com\/arcgis-blog\/products\/js-api-arcgis\/mapping\/explore-data-in-dynamic-workspaces-with-smart-mapping\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Build web apps for exploring data in dynamic workspaces\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.esri.com\/arcgis-blog\/products\/js-api-arcgis\/mapping\/explore-data-in-dynamic-workspaces-with-smart-mapping\" \/>\n<meta property=\"og:site_name\" content=\"ArcGIS Blog\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/esrigis\/\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:site\" content=\"@ESRI\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":[\"Article\",\"BlogPosting\"],\"@id\":\"https:\/\/www.esri.com\/arcgis-blog\/products\/js-api-arcgis\/mapping\/explore-data-in-dynamic-workspaces-with-smart-mapping#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.esri.com\/arcgis-blog\/products\/js-api-arcgis\/mapping\/explore-data-in-dynamic-workspaces-with-smart-mapping\"},\"author\":{\"name\":\"Kristian Ekenes\",\"@id\":\"https:\/\/www.esri.com\/arcgis-blog\/#\/schema\/person\/5469f723fbfb78138efbb1da56e6aa9b\"},\"headline\":\"Build web apps for exploring data in dynamic workspaces\",\"datePublished\":\"2018-09-04T15:00:09+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.esri.com\/arcgis-blog\/products\/js-api-arcgis\/mapping\/explore-data-in-dynamic-workspaces-with-smart-mapping\"},\"wordCount\":9,\"publisher\":{\"@id\":\"https:\/\/www.esri.com\/arcgis-blog\/#organization\"},\"keywords\":[\"data visualization\",\"dynamic layers\",\"jsapi4\",\"smart mapping\"],\"articleSection\":[\"Mapping\"],\"inLanguage\":\"en-US\"},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.esri.com\/arcgis-blog\/products\/js-api-arcgis\/mapping\/explore-data-in-dynamic-workspaces-with-smart-mapping\",\"url\":\"https:\/\/www.esri.com\/arcgis-blog\/products\/js-api-arcgis\/mapping\/explore-data-in-dynamic-workspaces-with-smart-mapping\",\"name\":\"Build web apps for exploring data in dynamic workspaces\",\"isPartOf\":{\"@id\":\"https:\/\/www.esri.com\/arcgis-blog\/#website\"},\"datePublished\":\"2018-09-04T15:00:09+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/www.esri.com\/arcgis-blog\/products\/js-api-arcgis\/mapping\/explore-data-in-dynamic-workspaces-with-smart-mapping#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.esri.com\/arcgis-blog\/products\/js-api-arcgis\/mapping\/explore-data-in-dynamic-workspaces-with-smart-mapping\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.esri.com\/arcgis-blog\/products\/js-api-arcgis\/mapping\/explore-data-in-dynamic-workspaces-with-smart-mapping#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.esri.com\/arcgis-blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Build web apps for exploring data in dynamic workspaces\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.esri.com\/arcgis-blog\/#website\",\"url\":\"https:\/\/www.esri.com\/arcgis-blog\/\",\"name\":\"ArcGIS Blog\",\"description\":\"Get insider info from Esri product teams\",\"publisher\":{\"@id\":\"https:\/\/www.esri.com\/arcgis-blog\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.esri.com\/arcgis-blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.esri.com\/arcgis-blog\/#organization\",\"name\":\"Esri\",\"url\":\"https:\/\/www.esri.com\/arcgis-blog\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.esri.com\/arcgis-blog\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2018\/04\/Esri.png\",\"contentUrl\":\"https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2018\/04\/Esri.png\",\"width\":400,\"height\":400,\"caption\":\"Esri\"},\"image\":{\"@id\":\"https:\/\/www.esri.com\/arcgis-blog\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/www.facebook.com\/esrigis\/\",\"https:\/\/x.com\/ESRI\",\"https:\/\/www.linkedin.com\/company\/5311\/\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.esri.com\/arcgis-blog\/#\/schema\/person\/5469f723fbfb78138efbb1da56e6aa9b\",\"name\":\"Kristian Ekenes\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.esri.com\/arcgis-blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2021\/10\/ekenes-zurich-213x200.png\",\"contentUrl\":\"https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2021\/10\/ekenes-zurich-213x200.png\",\"caption\":\"Kristian Ekenes\"},\"description\":\"Kristian Ekenes is a Principal Product Engineer at Esri specializing in data visualization on the web. He works on the ArcGIS Maps SDK for JavaScript, ArcGIS Arcade, and Map Viewer in ArcGIS Online. Kristian's work focuses on researching and developing new and innovative data visualization capabilities of geospatial data in web maps, Arcade integration in web maps, and applications of generative AI assistants in web maps. Prior to joining Esri, he worked as a GIS Specialist for an environmental consulting company. Kristian has degrees from Brigham Young University and Arizona State University.\",\"sameAs\":[\"https:\/\/github.com\/ekenes\",\"https:\/\/www.linkedin.com\/in\/kristian-ekenes\/\",\"https:\/\/x.com\/kekenes\"],\"gender\":\"male\",\"jobTitle\":\"Principal Product Engineer\",\"worksFor\":\"Esri\",\"url\":\"https:\/\/www.esri.com\/arcgis-blog\/author\/kekenes\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Build web apps for exploring data in dynamic workspaces","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.esri.com\/arcgis-blog\/products\/js-api-arcgis\/mapping\/explore-data-in-dynamic-workspaces-with-smart-mapping","og_locale":"en_US","og_type":"article","og_title":"Build web apps for exploring data in dynamic workspaces","og_url":"https:\/\/www.esri.com\/arcgis-blog\/products\/js-api-arcgis\/mapping\/explore-data-in-dynamic-workspaces-with-smart-mapping","og_site_name":"ArcGIS Blog","article_publisher":"https:\/\/www.facebook.com\/esrigis\/","twitter_card":"summary_large_image","twitter_site":"@ESRI","schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":["Article","BlogPosting"],"@id":"https:\/\/www.esri.com\/arcgis-blog\/products\/js-api-arcgis\/mapping\/explore-data-in-dynamic-workspaces-with-smart-mapping#article","isPartOf":{"@id":"https:\/\/www.esri.com\/arcgis-blog\/products\/js-api-arcgis\/mapping\/explore-data-in-dynamic-workspaces-with-smart-mapping"},"author":{"name":"Kristian Ekenes","@id":"https:\/\/www.esri.com\/arcgis-blog\/#\/schema\/person\/5469f723fbfb78138efbb1da56e6aa9b"},"headline":"Build web apps for exploring data in dynamic workspaces","datePublished":"2018-09-04T15:00:09+00:00","mainEntityOfPage":{"@id":"https:\/\/www.esri.com\/arcgis-blog\/products\/js-api-arcgis\/mapping\/explore-data-in-dynamic-workspaces-with-smart-mapping"},"wordCount":9,"publisher":{"@id":"https:\/\/www.esri.com\/arcgis-blog\/#organization"},"keywords":["data visualization","dynamic layers","jsapi4","smart mapping"],"articleSection":["Mapping"],"inLanguage":"en-US"},{"@type":"WebPage","@id":"https:\/\/www.esri.com\/arcgis-blog\/products\/js-api-arcgis\/mapping\/explore-data-in-dynamic-workspaces-with-smart-mapping","url":"https:\/\/www.esri.com\/arcgis-blog\/products\/js-api-arcgis\/mapping\/explore-data-in-dynamic-workspaces-with-smart-mapping","name":"Build web apps for exploring data in dynamic workspaces","isPartOf":{"@id":"https:\/\/www.esri.com\/arcgis-blog\/#website"},"datePublished":"2018-09-04T15:00:09+00:00","breadcrumb":{"@id":"https:\/\/www.esri.com\/arcgis-blog\/products\/js-api-arcgis\/mapping\/explore-data-in-dynamic-workspaces-with-smart-mapping#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.esri.com\/arcgis-blog\/products\/js-api-arcgis\/mapping\/explore-data-in-dynamic-workspaces-with-smart-mapping"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.esri.com\/arcgis-blog\/products\/js-api-arcgis\/mapping\/explore-data-in-dynamic-workspaces-with-smart-mapping#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.esri.com\/arcgis-blog\/"},{"@type":"ListItem","position":2,"name":"Build web apps for exploring data in dynamic workspaces"}]},{"@type":"WebSite","@id":"https:\/\/www.esri.com\/arcgis-blog\/#website","url":"https:\/\/www.esri.com\/arcgis-blog\/","name":"ArcGIS Blog","description":"Get insider info from Esri product teams","publisher":{"@id":"https:\/\/www.esri.com\/arcgis-blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.esri.com\/arcgis-blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.esri.com\/arcgis-blog\/#organization","name":"Esri","url":"https:\/\/www.esri.com\/arcgis-blog\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.esri.com\/arcgis-blog\/#\/schema\/logo\/image\/","url":"https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2018\/04\/Esri.png","contentUrl":"https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2018\/04\/Esri.png","width":400,"height":400,"caption":"Esri"},"image":{"@id":"https:\/\/www.esri.com\/arcgis-blog\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/esrigis\/","https:\/\/x.com\/ESRI","https:\/\/www.linkedin.com\/company\/5311\/"]},{"@type":"Person","@id":"https:\/\/www.esri.com\/arcgis-blog\/#\/schema\/person\/5469f723fbfb78138efbb1da56e6aa9b","name":"Kristian Ekenes","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.esri.com\/arcgis-blog\/#\/schema\/person\/image\/","url":"https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2021\/10\/ekenes-zurich-213x200.png","contentUrl":"https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2021\/10\/ekenes-zurich-213x200.png","caption":"Kristian Ekenes"},"description":"Kristian Ekenes is a Principal Product Engineer at Esri specializing in data visualization on the web. He works on the ArcGIS Maps SDK for JavaScript, ArcGIS Arcade, and Map Viewer in ArcGIS Online. Kristian's work focuses on researching and developing new and innovative data visualization capabilities of geospatial data in web maps, Arcade integration in web maps, and applications of generative AI assistants in web maps. Prior to joining Esri, he worked as a GIS Specialist for an environmental consulting company. Kristian has degrees from Brigham Young University and Arizona State University.","sameAs":["https:\/\/github.com\/ekenes","https:\/\/www.linkedin.com\/in\/kristian-ekenes\/","https:\/\/x.com\/kekenes"],"gender":"male","jobTitle":"Principal Product Engineer","worksFor":"Esri","url":"https:\/\/www.esri.com\/arcgis-blog\/author\/kekenes"}]}},"text_date":"September 4, 2018","author_name":"Kristian Ekenes","author_page":"https:\/\/www.esri.com\/arcgis-blog\/author\/kekenes","custom_image":"https:\/\/www.esri.com\/arcgis-blog\/app\/uploads\/2018\/09\/wide-1.png","primary_product":"ArcGIS Maps SDK for JavaScript","tag_data":[{"term_id":30111,"name":"data visualization","slug":"data-visualization","term_group":0,"term_taxonomy_id":30111,"taxonomy":"post_tag","description":"","parent":0,"count":97,"filter":"raw"},{"term_id":30801,"name":"dynamic layers","slug":"dynamic-layers","term_group":0,"term_taxonomy_id":30801,"taxonomy":"post_tag","description":"","parent":0,"count":5,"filter":"raw"},{"term_id":27491,"name":"jsapi4","slug":"jsapi4","term_group":0,"term_taxonomy_id":27491,"taxonomy":"post_tag","description":"","parent":0,"count":111,"filter":"raw"},{"term_id":24581,"name":"smart mapping","slug":"smart-mapping","term_group":0,"term_taxonomy_id":24581,"taxonomy":"post_tag","description":"","parent":0,"count":81,"filter":"raw"}],"category_data":[{"term_id":22941,"name":"Mapping","slug":"mapping","term_group":0,"term_taxonomy_id":22941,"taxonomy":"category","description":"","parent":0,"count":2690,"filter":"raw"}],"product_data":[{"term_id":36831,"name":"ArcGIS Maps SDK for JavaScript","slug":"js-api-arcgis","term_group":0,"term_taxonomy_id":36831,"taxonomy":"product","description":"","parent":36601,"count":362,"filter":"raw"},{"term_id":36601,"name":"Developers","slug":"developers","term_group":0,"term_taxonomy_id":36601,"taxonomy":"product","description":"","parent":0,"count":763,"filter":"raw"}],"primary_product_link":"https:\/\/www.esri.com\/arcgis-blog\/?s=#&products=js-api-arcgis","_links":{"self":[{"href":"https:\/\/www.esri.com\/arcgis-blog\/wp-json\/wp\/v2\/blog\/307942","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.esri.com\/arcgis-blog\/wp-json\/wp\/v2\/blog"}],"about":[{"href":"https:\/\/www.esri.com\/arcgis-blog\/wp-json\/wp\/v2\/types\/blog"}],"author":[{"embeddable":true,"href":"https:\/\/www.esri.com\/arcgis-blog\/wp-json\/wp\/v2\/users\/6561"}],"replies":[{"embeddable":true,"href":"https:\/\/www.esri.com\/arcgis-blog\/wp-json\/wp\/v2\/comments?post=307942"}],"version-history":[{"count":0,"href":"https:\/\/www.esri.com\/arcgis-blog\/wp-json\/wp\/v2\/blog\/307942\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.esri.com\/arcgis-blog\/wp-json\/wp\/v2\/media?parent=307942"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.esri.com\/arcgis-blog\/wp-json\/wp\/v2\/categories?post=307942"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.esri.com\/arcgis-blog\/wp-json\/wp\/v2\/tags?post=307942"},{"taxonomy":"industry","embeddable":true,"href":"https:\/\/www.esri.com\/arcgis-blog\/wp-json\/wp\/v2\/industry?post=307942"},{"taxonomy":"product","embeddable":true,"href":"https:\/\/www.esri.com\/arcgis-blog\/wp-json\/wp\/v2\/product?post=307942"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}