ArcGIS Maps SDK for JavaScript

Functions aren't fields; use Arcade instead

As of version 4.9 of the ArcGIS API for JavaScript (JS API), we removed support for rendering feature layers based on the result of a JavaScript function. In lieu of JavaScript functions we added support for Arcade expressions in renderers.


Prior to 4.9, the JS API allowed developers to pass a JavaScript function to the field property of a renderer and any visual variable. This provided the developer with the flexibility to calculate new values client-side and render the layer based on those values. This was great for the following reasons:

Check out the following app, which visualizes a FeatureLayer representing political boundaries in mainland China using a function set on the field property of the layer’s renderer. This is an above-and-below visualization, which categorizes each feature based on whether the percentage of the population without education is above or below the value of the feature selected by the user.

While powerful, renderers that use JavaScript functions as fields cannot be persisted and used for visualizations across the ArcGIS platform. There are a couple of reasons for this:

For these reasons, you were limited to using JavaScript functions as fields in renderers and visual variables in standalone web apps.

Arcade: A better approach

In December 2016, Esri introduced Arcade – an expression language for returning new data values client-side. Arcade can be used to calculate and return values for labels, popups, and renderers based on logic defined in an expression.

Several people have already written on various ways Arcade is and has been used for visualization in the JS API. Check out the following blogs to learn more about this.

Arcade provides many benefits that the JavaScript functions could not guarantee, including the following:

Because Arcade expressions allow you to create the same visualizations as those created using JavaScript functions, we are confident in removing support for JavaScript functions as fields in renderers.

Migrating JavaScript functions to Arcade expressions

If you’ve already created renderers with JavaScript functions, then you were likely familiar with the limitations.

So why take away this support? What about the benefits mentioned above? What if I want to create a visualization based on user input? What about access to outside features, or geometry operations?

The short answer to these questions is that Arcade allows you to create these visualizations.

Let’s check out the example above to learn how to migrate a renderer from using a JavaScript function as a field to using an Arcade expression. This example uses a JavaScript function in the field property of a UniqueValueRenderer.

valueFunction is the name of a function that takes an esri/Graphic instance as a parameter. This function executes for each feature at the time of rendering. For that reason, it is important to keep the code in this function light. Adding heavier code will come with a performance cost to the application.

Each time the user clicks a feature, the app updates the value of the value variable to the value of the clicked feature, causing the renderer to change.

I used the 4.9 version of the JS API to create the exact same app. But this time I pass an Arcade expression to the valueExpression property of the renderer.

The createArcade function returns an Arcade expression that determines whether the feature’s value is similar, above, or below the input value. Note how I use template literals to access the value of the selected feature and insert it to the Arcade expression. This same technique can be used to get user input from other DOM elements.

Since the clicked, or selected value, is a constant in the Arcade expression, the expression must be re-created with the new value and reset on the renderer. Once you update the renderer on the layer, the layer’s layer view will automatically refresh and update the visualization appropriately.

Now the final app looks like the following.

Keep in mind that while this version of the app doesn’t expose any functional differences from the previous version, it does redraw features more slowly than the 4.8 version of the app. We will improve performance in this regard at a future release.

Coming soon

In past conferences, such as the 2018 Esri User Conference, I’ve demonstrated other use cases that required using a JavaScript function as a field in a renderer. One such case is the app below, which visualizes restricted air space in the Gulf of Mexico based on their risk for encroachment by proposed oil rig locations. As you change the height of the proposed projects, you will see the renderer update accordingly. Read this blog post to learn more about how a similar app was created.

The JavaScript function referenced in this layer’s renderer uses the height obtained from a CSVLayer or as determined by the user along with the geometry engine to see if the features intersect buffers of the project areas.

We will add support for all Arcade geometry functions soon, making it possible to use Arcade for this use case with the 4.x JS API. Note that version 3.26 of the JS API already supports Arcade’s geometry functions, so you can use that API if your visualizations require them now.

About the author

Kristian is a Principal Product Engineer at Esri specializing in data visualization. He works on the ArcGIS Maps SDK for JavaScript, ArcGIS Arcade, and Map Viewer in ArcGIS Online. His goal is to help developers be successful, efficient, and confident in building web applications with the JavaScript Maps SDK, especially when it comes to visualizing data. Prior to joining Esri, he worked as a GIS Specialist for an environmental consulting company. He enjoys cartography, GIS analysis, and building GIS applications for genealogy.


Next Article

Multi-Scale Contour Styling in ArcGIS Pro

Read this article