Skip to content

Advanced formatting

In Experience Builder, you can use data attributes, statistics, and simple expressions to display basic dynamic content. You can also apply static and state-based styles in widget settings.

There are two types of advanced formatting—advanced dynamic content and dynamic styling.

  • Advanced dynamic content involves running calculations with data and returning dynamic values to display as widget content. You can use Arcade expressions to create advanced dynamic content.

  • Dynamic styling involves updating widget backgrounds, borders, and other visual elements based on data. You can use both Arcade expressions and conditional styling, a no-code feature, to create dynamic styling.

Arcade

Arcade is a lightweight and secure expression language you can use to manipulate data and create custom content in Experience Builder apps. You can use Arcade to create both dynamic content and dynamic styling.

Formatting profiles

A formatting profile defines the environment and rules for evaluating and interpreting expressions.

Experience Builder has two types of formatting profiles:

  • The widget formatting profile customizes the content and styling of individual widgets. It uses the $dataSource profile variable to reference data at the data source level.

  • The list item widget formatting profile customizes the content and styling of individual list items in a List widget, and widgets including Text, Button, and Image widgets within a list item. It uses the $feature profile variable to reference data at the feature level.

In all cases in Experience Builder, you enter scripts in an Arcade editor. The editor provides access to supported variables, functions, and live data previews that help you test scripts.

The Arcade editor appears in different parts of the builder interface, depending on whether you are using Arcade to create dynamic content, create dynamic styling, or add data.

Advanced dynamic content with Arcade

Dynamic content is content that changes based on data or user interactions. Arcade allows you to calculate and return dynamic values to display as widget content. Instead of binding content directly to a field or statistic, you can write expressions that compute values based on logic, conditions, and functions.

The value returned must be one of the following field types:

  • Text

  • Number

  • Date

  • Date Only

  • Time Only

Experience Builder supports using dynamic content in the following ways:

  • Creating text content, including button text

  • Setting image sources

  • Setting links by URL, excluding links in Text widgets

Sample Arcade scripts

The subsections below include Arcade scripts you can use to create dynamic content.

Display a message based on a condition

Use dark colors for code blocksCopy
1
return IIf($feature.status== "Delayed", "⚠️ Delayed", "✅ On Schedule");

Show the number of days since a record was last updated

Use dark colors for code blocksCopy
1
2
var lastUpdated = $feature.EditDate;
return Floor(DateDiff(Now(), lastUpdated, "days")) + " days ago";

Display a count of unique values

Use dark colors for code blocksCopy
1
2
3
4
var ds = $dataSources["dataSource_id"].layer;
var distincItem = Distinct(ds, 'CNTRY_NAME');

return Count(distincItem);

Display a message after applying a filter

Use dark colors for code blocksCopy
1
2
3
4
5
6
7
8
9
10
11
12
var ds = $dataSources["dataSource_1-18c66465e65-layer-2"].layer;

var queryStr = $dataSources["dataSource_1-18c66465e65-layer-2"].queryParams.where;

Console(queryStr);

if (!IsEmpty(queryStr)) {
  var result = Filter(ds, queryStr);
  return "Filtered view: " + Count(result) + " records are displayed.";
}

return "All records are displayed."

Shorten long texts in a List widget

Use dark colors for code blocksCopy
1
2
3
var desc = $feature.description;

return Left(desc, 10) + IIf(Count(desc) > 10, "...", "");

Display different images in an Image widget in a list based on category

Use dark colors for code blocksCopy
1
2
3
4
5
6
7
if ($feature.category === "park") {
  return "https://example.com/images/park.png";
} else if ($feature.category === "school") {
  return "https://example.com/ images /school.png";
} else {
  return "https://example.com/ images /default.png";
}

Styling dynamic content

For text content, you can return a dictionary that includes both a value and its text styles. The following is an example script:

Use dark colors for code blocksCopy
1
2
3
4
5
6
7
return {
  value: "Advanced dynamic content",
  text: {
    size: 16,
    bold: true
  }
};

You can also return a value in HTML format to create more advanced styling. The following is an example script that uses HTML:

Use dark colors for code blocksCopy
1
2
3
4
5
6
7
8
9
10
11
return "<p style=\"font-family: Arial; font-size: 16px; color: #333; margin-bottom: 12px;\">" +
"Welcome to Experience Builder! Visit our " +
"<a href=\"https://experience.arcgis.com\" style=\"color: #007BFF; text-decoration: none;\">" +
"homepage</a> for more details.</p>" +
"<p style=\"font-size: 15px; font-family: Verdana; color: #444; margin-bottom: 8px;\">" +
"Key features:</p>" +
"<ul style=\"font-size: 14px; font-family: Verdana; color: #444; margin-top: 0;\">" +
"<li style=\"margin-bottom: 6px;\">Interact with 2D and 3D content in one app.</li>" +
"<li style=\"margin-bottom: 6px;\">Deploy responsive apps to any device.</li>" +
"<li style=\"margin-bottom: 6px;\">Create, deploy, and manage apps in a single place.</li>" +
"</ul>"

The following table lists the HTML tags that Experience Builder supports in Arcade scripts:

TagAttributes
h1, h2, h3, h4, h5, h6style
spanstyle
pstyle
sstyle
strongstyle
emstyle
ustyle
ol, ulstyle
listyle
br
astyle, href, target
imgstyle, src, alt, height, width

Dynamic style with conditions or Arcade

Dynamic styling allows you to visually adapt widgets based on data. This includes changing visuals such as text size, background color, and border style based on field values, statistics, or calculated logic.

The Dynamic style setting appears in the settings panel of a widget when you connect the widget to data.

The following widgets support dynamic style:

  • Text widget—The Dynamic style setting appears at the bottom of the settings panel.

  • Button widget—The Dynamic style setting appears under Advanced. Each state (Default and Hover) has its own setting.

  • List widget—The Dynamic style setting appears under each state (Default, Hover, and Selected).

Turn on Dynamic style and click the settings button to open the Dynamic style panel. The panel includes two tabs: Condition and Script.

Condition

Conditional style is a no-code option that allows you to apply styles based on simple rules. It requires no scripting. It is the recommended method for visually emphasizing differences in data, such as status indicators, categories, and value ranges.

The Condition tab includes the following settings:

  • Select an indicator for conditions—Select a method for creating conditional statements. With the Text and Button widgets, you can use data attributes, statistics, or previously configured dynamic content. With the List widget, you can only use data attributes.

    The following table lists the types of attribute fields you can use as indicators and their supported operators.

    Indicator field typeSupported operators
    Stringis, is not, contains, is blank, is not blank
    Numberis, is not, is greater than, is less than, is between
  • Style conditions—Once you set an indicator, you can click Add style condition to create conditions. Each condition consists of the following components:

    • Operator—Choose from a list of operators supported by the indicator.

    • Value—The target value to compare against the indicator. Click Select source type to choose an input method, including user input, field, unique, and, for numeric indicators, statistics.

    • Style—The visual styling—such as text color, background, or border—applied when the condition is met.

You can select a condition in the settings panel to preview its effect on the canvas even if the current data does not meet the condition. You can re-order, duplicate, and delete conditions. If the current data matches multiple conditions, the one you place higher in the condition list takes priority. If the current data matches no conditions, the widget uses its static styling.

Script

You can use Arcade scripts to create complex and flexible style logic. From the Script tab, you can click Arcade Editor to open the editor window.

Experience Builder saves your script locally, and it remains available the next time you open the editor. To run a script, click Apply. When you do, the applied script appears in the Script in use box.

With the Arcade editor, instead of configuring style rules with a no-code interface, you write a script that returns a dictionary of style properties and their corresponding values. This allows you to apply styles based on custom logic, calculations, and conditions that cannot be achieved with the Style condition feature.

Experience Builder uses returned values to display a widget's style. If you enter any style keys that are not in the dictionary, the widget uses default style settings for those properties.

The tables below list the supported style properties for each widget, including the expected value types and their meanings.

Text widget styling

The Text widget supports the following style properties:

PropertyTypeDescription
textDictionaryUsed to set text style
text.sizeNumberFont size in pixels
text.colorStringText color
text.boldBooleanIndicates whether to use bold style
text.italicBooleanIndicates whether to use italic style
text.underlineBooleanIndicates whether to use underline style
text.strikeBooleanIndicates whether to use strike style
backgroundDictionaryUsed to set the background
background.colorStringBackground color
background.fillTypeString'fit', 'fill', 'center', 'tile', or 'stretch'
background.imageStringImage URL

The following is an example script that styles a city name in the Text widget with different text sizes and background colors depending on the population of the selected city:

Use dark colors for code blocksCopy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// Get the list of selected features from the data source
var sf = $dataSources["dataSource_id"].selectedFeatures;

// Get the population of the first selected feature
var pop = First(sf).Population;

// Initialize style variables
var bgColor = "";
var txtStyles = null;

// Apply style based on population threshold
if (pop > 500000) {
  bgColor = "rgba(238, 246, 255, 1)";
  txtStyles = {
    size: 34,
    bold: true
  };
} else {
  bgColor = "rgba(255, 216, 219, 1)";
  txtStyles = {
    size: 25,
    italic: true
  };
}

return {
  background: {
    color: bgColor
  },
  text: txtStyles
};

Button widget styling

The Button widget supports the following style properties:

PropertyTypeDescription
textDictionaryUsed to set text style
text.sizeNumberFont size in pixels
text.colorStringText color
text.boldBooleanIndicates whether to use bold style
text.italicBooleanIndicates whether to use italic style
text.underlineBooleanIndicates whether to use underline style
text.strikeBooleanIndicates whether to use strike style
iconDictionaryUsed to set icon style
icon.nameStringIcon name
icon.positionString'LEFT' or 'RIGHT'
icon.sizeNumberIcon size in pixels
icon.colorStringYou can set the icon color if the icon is in SVG format
backgroundDictionaryUsed to set the background
background.colorStringBackground color
background.fillTypeString'fit', 'fill', 'center', 'tile', or 'stretch'
background.imageStringImage URL
borderDictionaryUsed to set border style
border.borderDictionarySet the same style for all borders
border.border.typeString'solid', 'dashed', 'dotted', or 'double'
border.border.colorStringBorder color
border.border.widthNumberBorder width
border.borderLeftDictionarySet left border style. The dictionary format is the same as border.border.
border.borderRightDictionarySet right border style. The dictionary format is the same as border.border.
border.borderTopDictionarySet top border style. The dictionary format is the same as border.border.
border.borderBottomDictionarySet bottom border style. The dictionary format is the same as border.border.
borderRadiusDictionaryUsed to set the border radius
borderRadius.unitString'px', 'rem', 'em', 'vw', or '%'
borderRadius.numberNumber[][top-left-radius, top-right-radius, bottom-right-radius, bottom-left-radius]

The following is an example script that changes a Button widget icon based on the delivery status of an order:

Use dark colors for code blocksCopy
1
2
3
4
5
6
7
8
var status = $feature.deliveryStatus;
var isDelivered = status == "Delivered";

return {
  icon: {
    name: IIf(isDelivered, "check", "glasses")
  }
};

List widget styling

The List widget supports the following style properties for each list item:

PropertyTypeDescription
backgroundDictionaryUsed to set the background
background.colorStringBackground color
background.fillTypeString'fit', 'fill', 'center', 'tile', or 'stretch'
background.imageStringImage URL
borderDictionaryUsed to set border style
border.borderDictionarySet the same style for all borders
border.border.typeString'solid', 'dashed', 'dotted', or 'double'
border.border.colorStringBorder color
border.border.widthNumberBorder width
border.borderLeftDictionarySet left border style. The dictionary format is the same as border.border.
border.borderRightDictionarySet right border style. The dictionary format is the same as border.border.
border.borderTopDictionarySet top border style. The dictionary format is the same as border.border.
border.borderBottomDictionarySet bottom border style. The dictionary format is the same as border.border.
borderRadiusDictionaryUsed to set the border radius
borderRadius.unitString'px', 'rem', 'em', 'vw', or '%'
borderRadius.numberNumber[][top-left-radius, top-right-radius, bottom-right-radius, bottom-left-radius]

The following is an example script that gives a different background color to list items that have a high priority level:

Use dark colors for code blocksCopy
1
2
3
4
5
6
7
var isHigh = $feature.priority == "High";

return {
  background: {
    color: IIf(isHigh, "rgba(217, 249, 242, 1)", "rgba(255, 238, 194, 1)")
  }
};

Best practices and usage notes for Arcade

The following is a list of best practices and notes for using Arcade scripts to generate dynamic content and dynamic style:

  • Arcade scripts in Experience Builder only support FeatureLayer , OrientedImageryLayer , SubtypeGroupLayer , and SubtypeSublayer layer types.

  • Filters and spatial filters applied to data sources or data views cannot be automatically added to profile data sources. Use the getFilteredFeatureSet function to manually synchronize the filter.

  • For the widget formatting profile, the Arcade script uses the current data to test the script when you run or apply it. For example, if you use selectedFeatures and there is no selection, the script will display a message stating Invalid Arcade Script unless you have handled the case of no selection.

  • For the List item widget formatting profile, when you run or apply the Arcade script, it uses the first list item to test the script.

  • Each app page supports a maximum of 10 Arcade expressions using the widget formatting profile, including both dynamic content and dynamic style set by the Arcade script.

  • If you use an aggregation value in multiple places, use the Arcade option in the Add data window to add it once and use it elsewhere.

  • Fields used in the widget formatting profile are not automatically added to the used fields list. If these fields are not referenced elsewhere, the Arcade script may run incorrectly and result in an incorrect output.

Your browser is no longer supported. Please upgrade your browser for the best experience. See our browser deprecation post for more details.