July 2020
Layer blending
We are introducing a new capability called layer blending. This powerful capability allows you to apply one of more than 30 blend modes to your layers to create interesting effects, or even to produce what seems like a new layer. This is done by applying the desired blend mode by setting the layer's blendMode property.
In the following screenshot, we see the result of applying destination-in
blendMode to an imageryLayer that displays areas of cultivated crops with a black color. This layer is displayed over the county crops feature layer. The result of destination-in
blendMode shows contents of the featurelayer where two layers overlap while everything else is removed. With one line of a code, we are able to create a focused map that shows the cultivated areas in US. To see the blend mode in action, please check out layer blending samples.

Clustering updates
Labeling point clusters
You can now label clusters with the count of points represented by the cluster.

Or any summary statistics used by the cluster popup, such as average of a number field, and predominant value of a string field.

Labeling is configured on the labelingInfo property of FeatureReductionCluster. You can take advantage of all LabelClass functionality when labeling clusters.
layer.featureReduction = {
type: "cluster",
clusterRadius: "100px",
clusterMinSize: "24px",
clusterMaxSize: "60px",
labelingInfo: [{
// disabling label deconfliction ensures
// all cluster counts are displayed
deconflictionStrategy: "none",
labelExpressionInfo: {
// Displays the cluster count in the center of the cluster
expression: "Text($feature.cluster_count, '#,###')"
},
symbol: {
type: "text",
color: "#004a5d",
font: {
weight: "bold",
family: "Noto Sans",
size: "12px"
}
},
labelPlacement: "center-center",
}]
};
The following are aggregate fields you can reference in your cluster labels.
// cluster count
$feature.cluster_count
// If a number field is used in the layer's renderer
// you can display the average value of this field
// within each cluster
$feature.cluster_avg_{fieldName}
// If a UniqueValueRenderer is applied to the layer
// you can display the predominant type of
// features in each cluster
$feature.cluster_type_{fieldName}
Generate defaults for clusters
You can use the following convenience methods for generating default labels and popup templates for clustering based on the layer's renderer.
The Clustering - generate suggested configuration sample demonstrates how to use these functions.

OGCFeatureLayer
The new OGCFeatureLayer can be used in a MapView or SceneView to create a layer based on individual collections from a OGC API Features service. You can work with these features from the service similar to our FeatureLayer, by adding your own rendering, labeling, clustering, etc.
The OGC API Features standard is the successor to the earlier OGC Web Feature Service (WFS) specification. The new standard is better, faster, and follows a modernized approach that is consistent and modularized. Note that support for WFS is still under consideration. However, the OGC API Features is adopted by several server implementations and is a better and faster option than WFS for consuming data.

3D Updates
Water reflections
Buildings, mountains and other 3D objects are now reflected on water surfaces, making scenes that use the WaterSymbol3DLayer look more realistic than ever. In addition animated waves and reflected sunlight are more visible from top down views.

Check out the updated sample to see how you can toggle reflections for water bodies.
Integrated mesh modifications
Change the shape of an IntegratedMeshLayer by applying client-side modifications. A new class SceneModifications changes the outline or flatten parts of an integrated mesh using polygon geometries. This allows you to focus on specific areas of the mesh, trim its outline or load alternative 3D data using a single IntegratedMeshLayer.
SceneModifications can be persisted using Web
, allowing users to share their modified integrated mesh through web scenes. See how you can interactively modify IntegratedMeshLayers using the Sketch widget in this new sample.

New BuildingExplorer widget
Better understand comprehensive building data coming from BIM models using the new BuildingExplorer widget. Preconfigured and intuitive UI components allow you to isolate specific levels, categories or construction phases for one or multiple buildings in your scene.
To customize the UI for your specific BIM workflows, the widget provides simple options to toggle the visibility for each component.

Try out the BuildingExplorer in the updated Filter BuildingSceneLayer sample.
Improved Slice tool
Provide users specific and predefined viewpoints of interior and underground details in your scene. When slicing through terrain and 3D objects, it's now possible to arbitrarily tilt the slice plane and also programmatically set the slice shape using a new class SlicePlane.

Check out the Slice sample to see how you can customize the behavior and UI of the widget.
SceneView memory
Gather insights on the performance and memory consumption of layers in your scene. Depending on the complexity of a scene and the amount of available memory, the SceneView might not be able to render all features.
A new sample shows how you can use Scene
to inspect the amount and complexity of visualized data in your scene. Please note that this property is experimental and should therefore only be used for debugging purposes.

Symbol updates
CIMSymbol lines and polygons
CIMSymbol now supports CIMLineSymbol and CIMPolygonSymbol. Create custom symbols in your visualizations by using multiple symbol layers to achieve your desired effect. See the CIM specification for more details. CIM lines and polygons are not currently supported in 3D SceneViews. Click here for the full list of limitations.

Draw lines with marker symbols
The SimpleLineSymbol now supports markers of different styles (arrow, diamond, cross, etc.) at the beginning and/or end of each line symbol in a 2D MapView. Markers can enhance the cartographic information of a line by providing additional visual cues about the associated feature.

Imagery layer updates
The RasterShadedReliefRenderer and RasterColormapRenderer are new at 4.16 and can be used to render ImageryLayer and ImageryTileLayer. To see how the RasterShadedReliefRenderer in action, please refer to the ImageryTileLayer - shaded relief renderer sample.
The Tile
is removed and replaced by the ImageryTileLayer and the popupTemplate is now supported on the new class.

Webmap saving updates
We enhanced our support for reading and writing the WebMap.initialViewProperties property (extent, rotation, and scale). Also, added support for reading and writing CIM symbols in web maps.
Widget updates
FeatureTable widget (Beta release)
We’ve added editing support to the FeatureTable widget. In order to enable editing within the table, set the editingEnabled property to true
. This allows updating values within a table’s cell via double-clicking on it. Note that the service hosting the data must be enabled to allow editing. The FeatureTable is similar to other client editing APIs in that it does not override the permissions set on the service.
Editing date fields is not yet supported but is planned in a future release.
In addition to allowing editing at the tabular level, it is possible to configure editing functionality per field. This is handled via the editable property within the table’s field configs.
To see editing within the FeatureTable, please check out the FeatureTable widget with editing enabled sample.

FormTemplate
A new class was added to aid in formatting the FeatureForm widget. The FormTemplate can be set directly on a FeatureLayer, a FeatureForm, or its view model. The template consists of various elements that display a specific type of form data. The two that are currently supported are field and group. Field elements provide a mechanism to format data collection for field input, whereas group elements are a grouping of multiple field elements nested into one group. Additional types will be added in future releases.
Prior to this version, any type of field configuration for the form was handled by setting its fieldConfigs to an array of FieldConfigs and/or FieldGroupConfigs. The preferred way to do this now is with FieldElements and GroupElements. The older method of using field
is still supported but will eventually be deprecated in the future in favor of setting the elements directly within the layer's or form's form
property. The images below depict how a form displays when configuring its fields via fieldConfigs in comparison to setting the fields via the form template's elements. There is no detectable difference in how it renders within the UI.
Fields configured via the form's field | Fields configured via the template's elements |
---|---|
![]() |
![]() |
For an example of how to do this, please refer to the updated Update Feature Attributes sample which sets the form
on the FeatureLayer and another updated sample, Advanced Attribute Editing, which sets the form
on the FeatureForm directly.
Popup
New Custom content element
A new popup element, CustomContent, was added at 4.16. Now in addition to fields
, media
, text
, and attachments
, we now have an additional custom
type. This type of content element can work with multiple types of content such as strings, HTMLElements, Widgets, and/or a Promise.
To see an example of this type of popup content, please check out the Custom popup content sample.

Smart detection of fields
The default Popup has been improved to no longer display system fields that do not hold significant value, e.g. Shape_
and Shape_
are two fields that no longer display.
Popup utility
A new popupUtils object was added. This contains three utility functions to aid in Popup content creation.
API Modernization
At the 2020 Esri Developer Summit, we announced that we were working on a project to modernize how the ArcGIS Maps SDK for JavaScript is consumed for seamless integration with frameworks and developer tooling. Here are the current enhancements:
- Native Promises have been activated by default. The
has
flag"esri-native-promise"
is no longer supported. - Localization has been improved. The preferred way to set an application's locale is at runtime via the intl.setLocale() method. Please refer to the updated Localization guide topic for additional details regarding this.
- Classes are now using native class syntax instead of
dojo/_base/declare
. If you built classes like custom widgets, then now is a good opportunity to make some updates. - Multiple class inheritance is no longer supported.
- The current class syntax still works but will be deprecated. To update your TypeScript classes:
- Remove the
amd-dependency
comments, they are no longer necessary. - Add
import
to your tsconfig.json compiler options. See TypeScript documentation for more details.Helpers: true - Remove use of Dojo’s
declare
module. This means that apps with classes that leverage the API class framework and multiple inheritance will stop working. The recommended approach is to use mixins with Accessor.
- Remove the
Here is an example of the syntax before and after this update:
Previous TypeScript syntax
/// <amd-dependency path="esri/core/tsSupport/declareExtendsHelper" name="__extends" />
/// <amd-dependency path="esri/core/tsSupport/decorateHelper" name="__decorate" />
import Accessor = require("esri/core/Accessor");
import { subclass, declared } from "esri/core/accessorSupport/decorators";
@subclass("esri.guide.Color")
class Color extends declared(Accessor) {
}
New TypeScript syntax
import Accessor = require("esri/core/Accessor");
import { subclass } from "esri/core/accessorSupport/decorators";
@subclass("esri.guide.Color")
class Color extends Accessor {
}
Labeling updates
The LabelClass.deconflictionStrategy property defines how labels should be placed relative to one another for FeatureLayer, CSVLayer, and StreamLayer in 2D MapViews. By default, labels have a static
deconfliction strategy, meaning labels that overlap are dropped to make them easier to read. While we've had label deconfliction for awhile, we are now providing an option to turn it off. This provides developers with the flexibility to display all labels when appropriate.
Smart mapping modules have a new home
Because Smart Mapping no longer applies only to renderers, we reorganized the module structure to more clearly indicate which properties of the FeatureLayer you may use to generate good default renderers, popupTemplates, and labels.
These modules previously resided in esri/renderers/smart
folders.
esri/
renderers/
smartMapping/
creators/
heuristics/
statistics/
symbology/
Now the structure follows the following format:
esri/
smartMapping/
heuristics/
labels/ // new at 4.16
popup/ // new at 4.16
renderers/ // renamed from `creators`
statistics/
symbology/
See the deprecated classes below for a complete list of changes.
Generate popup template from renderer
You can now generate default popup templates that only includes data used in the layer's renderer.
popupTemplateCreator.getTemplates({
layer: layer
}).then(function(response){
// a suggested popupTemplate for the layer based on its renderer
layer.popupTemplate = response.primaryTemplate.value;
});
This provides a better default popup template than the traditional approach of providing a long table of unformatted values.
Suggested default template based on renderer | Traditional default |
---|---|
![]() |
![]() |
The following samples were updated to demonstrate how to use this method:
Arcade template literals
You can now leverage template literals within Arcade expressions. The Summarize intersecting points in a popup sample demonstrates how to use template literals in an expression referenced in a PopupTemplate.
var output = "";
if(Count(topCrimes) == 0){
return "No crimes committed in this area";
}
var num = 0;
for(var item in topCrimes){
num++;
var num_crimes = item.total;
var crimeType = item["desc_"];
var timeOfDay = When(
item.night_avg >= 0.6, "at night",
item.night_avg <= 0.4, " during the daytime hours",
" at both night and day");
////////////////////////////////////////////////////////
//
// Display crime type with count using template literals
//
////////////////////////////////////////////////////////
output += `${num}. ${crimeType}
-- Total offenses: ${Text(num_crimes, "#,###")}
-- Most crimes were reported ${timeOfDay}
`;
}
return output;
This is cleaner than concatenating multiple strings with hardcoded newline characters.
output += num + ". " + crimeType + "\n" +
"-- Total offenses: " + Text(num_crimes, "#,###") + "\n" +
"-- Most crimes were reported " + timeOfDay + "\n\n";
Breaking changes
- Removed Dojo promises. Native Promises have been activated by default. The
has
flag"esri-native-promise"
is no longer supported. - Removed use of Dojo’s
declare
module. This means that apps with classes that leverage the API class framework and multiple inheritance will stop working. The recommended approach is to use mixins with Accessor. - The
Tile
is removed and replaced by the ImageryTileLayer.Imagery Layer - The TimeExtent's intersection method now returns an instance of TimeExtent with
undefined
values for start and end properties if the two time extents do not intersect. - The suspended property of the View is now set to
false
when the view container's css stylevisibility
is set tohidden
(visibility:
). The view is hidden but it renders and updates data now.hidden - CIMSymbol's data property now only supports CIMSymbolReference JSON. The CIMSymbol JSON should be applied at
cim
.Symbol.data.symbol
Please refer to the Breaking Changes guide topic for a complete list of breaking changes across all releases of the 4x API.
Bug fixes and enhancements
- BUG-000117528 & ENH-000116007: Added support for arrow marker symbols on the end of lines.
- BUG-000117869 Fixed an issue where changing the field alias for the
cluster_
attribute in point clustering wasn't displaying properly in the Legend.count - BUG-000125118: Fixed an issue where SVG symbols were unable to be printed if added as a PictureMarkerSymbol.
- BUG-000127749: Fixed an issue where the
stationary
property in MapView and SceneView was handled inconsistently. - BUG-000128066: Fixed an issue where an ImageryLayer was throwing an error when the layer is added from portalItem.
- BUG-000128672: Fixed an issue where the FeatureForm would not validate text fields for
NULL
values if the field did not allow this. - BUG-000129390: Fixed an issue where the LayerSearchSource.zoomScale property fails to set zoom scale for the selected search result.
- BUG-000129738: Fixed an issue in LayerList where actions with the visible property set to false are still visible.
- BUG-000130303: Updated the documentation to state that PictureMarkerSymbol does not support PNG symbols in Internet Explorer 11.
- BUG-000130363: Fixed an issue where the Sublayer.clone() method wasn't doing deep cloning properly.
- BUG-000130559: The ScaleBar widget now displays the correct distance when padding is set on the MapView.
- BUG-000130770: Fixed an issue where UniqueValueRenderer failed to display multiple SimpleMarkerSymbols if the only difference between the symbols was a value in an outline.
- GEONET-251354: Fixed an issue where the PrintTemplate did not support custom print templates, which affected both the PrintTask and Print widget.
- GEONET-253742: Fixed an issue where client-side FeatureLayer fails to display >60,000 features.
- GEONET-254318: Fixed an issue where multipoints create artifacts at the tile boundaries.
- GEONET-254997: Fixed an issue where RasterStretchRenderer.statistics is not converted to server stats properly.
- Fixed an issue where reordering stops in the Directions widget could cause display issues.
- Fixed an issue where the Map and widgets stop rendering when the View container div
visibility
is set tohidden
. - Fixed an issue where the Sublayer capabilities.operations.supportsQuery did not work properly for all layer types.
- Fixed an issue where the printed legend was styled incorrectly when using a RelationshipRenderer or a DotDensityRenderer. Requires a print service from version 10.8.1 or higher.
- Improved shadow rendering: fixed artifacts along the edges of shadows casted by 3D objects.
- Enhanced the 3D editing widget to now use the same visual tools and helpers for creating and updating features.
- Enhanced the Directions widget and Search widget to display a notification when a user selects
Use current location
and the current location cannot be retrieved due to current browser restrictions or settings. - Enhanced the Directions widget to allow the user to select a source from multiple searchProperties.sources.
- Enhanced the Directions widget to display times based on stop locations.
- Enhanced the Directions widget to include placeholder text for custom locators.
- Enhanced the MapView.hitTest() method to add an
options
parameter to include or exclude layers or graphics from the hitTest. - Enhanced the Sublayer.createFeatureLayer() method to include the MapImageLayer.refreshInterval property value (if defined) for the created FeatureLayer.
Added classes, properties, methods, events
Complete list of added classes, properties, methods, events.
Deprecated classes, properties, methods, events
Complete list of deprecated classes, properties, methods, events.
Additional packages
Version 4.16 of the ArcGIS Maps SDK for JavaScript uses ArcGIS Arcade 1.11 (since 4.16), From Dojo 5 we use @dojo/framework version 5.0.4 (since 4.12).
How to access the SDK
- The API is available on both CDN and npm, Read more at Install and set up.
- You can also download both the documentation and the API library. These downloads are typically available 3-4 weeks after release.
Previous releases
- Version 4.27 - June 2023
- Version 4.26 - February 2023
- Version 4.25 - November 2022
- Version 4.24 - June 2022
- Version 4.23 - March 2022
- Version 4.22 - December 2021
- Version 4.21 - September 2021
- Version 4.20 - June 2021
- Version 4.19 - April 2021
- Version 4.18 - December 2020
- Version 4.17 - October 2020
- Version 4.16 - July 2020
- Version 4.15 - April 2020
- Version 4.14 - December 2019
- Version 4.13 - October 2019
- Version 4.12 - June 2019
- Version 4.11 - March 2019
- Version 4.10 - December 2018
- Version 4.9 - September 2018
- Version 4.8 - July 2018
- Version 4.7 - April 2018
- Version 4.6 - December 2017
- Version 4.5 - September 2017
- Version 4.4 - July 2017
- Version 4.3 - March 2017
- Version 4.2 - December 2016
- Version 4.1 - September 2016
- Version 4.0 - May 2016