الدرس 2 · الوحدة 4: Advanced Formatting and Data Expressions
Arcade advanced formatting for indicators, lists and tables
الفيديو قريبًا
Learn it with your tutor on the live board
أهم نقاط الفيديو
The number nobody noticed
- Storm night: 1,284 open outages on the big indicator
- Same grey card as a calm Tuesday
- Outage list: every row looks identical
- The data was right; the formatting hid the urgency
What you will learn
- Write Arcade expressions that style indicators by thresholds
- Color and enrich list rows with computed text
- Style individual table cells, per field and per row
- Test threshold rules in Python first
Arcade in one minute
- Arcade: Esri's small expression language
- Runs inside ArcGIS Online, Dashboards, Field Maps and more
- Each place it runs is a "profile" with its own variables
- Dashboards formatting profile gives you $datapoint (and $reference for indicators)
How advanced formatting works
- Runs once per indicator, list row or table row
- Reads values from $datapoint (and $reference)
- Returns a dictionary: style keys and values
- The dashboard applies the dictionary when it draws
Worked example: outage indicator
var red = '#c62828'
var amber = '#f9a825'
var green = '#2e7d32'
var open = $datapoint.count_objectid
var ref = $reference.count_objectid
var color = green
var ink = '#ffffff'
var level = 'NORMAL'
if (open > 500) { color = red; level = 'SEVERE' }
else if (open > 200) {
color = amber; ink = '#1a1a1a'; level = 'HIGH'
}
return {
backgroundColor: color,
textColor: ink,
topText: level,
middleText: Text(open, '#,##0'),
bottomText: Text(open - ref, '+#,##0;-#,##0') + ' vs yesterday'
} Test the rules in Python first
def style(now, ref):
if now > 500:
color = "red"
elif now > 200:
color = "amber"
else:
color = "green"
return color, f"{now - ref:+,} vs yesterday"
cases = [(150, 180), (200, 190), (500, 480), (1284, 610)]
for now, ref in cases:
print(now, style(now, ref)) Lists: flag urgent service requests
var p = $datapoint.priority
var bg = ''
if (p == 'High') { bg = '#fde0dc' }
else if (p == 'Medium') { bg = '#fff4d6' }
var d = DateDiff(Now(), $datapoint.opened, 'days')
return {
backgroundColor: bg,
attributes: { age: Round(d, 1) + ' days open' }
}
// line item template: {expression/age} Tables: style single cells
var dia = $datapoint.diameter_in
var st = $datapoint.status
return {
backgroundColor: IIf(st == 'Open', '#fff4d6', ''),
cells: {
diameter_in: {
displayText: dia + ' in',
backgroundColor: IIf(dia >= 12, '#fde0dc', '')
},
status: {
displayText: Upper(st),
textColor: IIf(st == 'Open', '#c62828', '#2e7d32')
}
}
} Keep it readable and consistent
- Store colors once in variables at the top
- Use soft backgrounds, strong text for alerts
- Always add a word or icon, not color alone
- Format numbers with Text: 1,284 not 1284.0
Common mistake: empty values
- A missing value quietly shows wrong text or numbers
- One empty field can show wrong text or drop a row's styling
- Guard with DefaultValue or IsEmpty
- Key names are exact: backgroundColor, not bgColor
Recap
- Advanced formatting returns a dictionary of styles
- Indicators, lists and tables each have their own keys
- Test thresholds at the edges and guard empty values
Exercise
- Use a Living Atlas or your own incidents layer
- Indicator: open incidents, green, amber, red by threshold
- Bottom text: change versus a reference value
- List: highlight one category, add "hours since reported"
النص المكتوب
The number nobody noticed. Picture a storm night at an electric utility. The operations dashboard shows one big indicator: 1,284 open outages. It's the same grey card, in the same grey font, that showed 40 outages last Tuesday. Beside it, a list of crews and incidents where every row looks identical, so the hospital feeder outage sits quietly between two streetlight tickets. The data was correct, but the screen didn't tell anyone it was a bad night. The manager only noticed when the phones started ringing. This lesson fixes exactly that. You'll make the numbers and rows change their own look based on what the data says, so the urgent things stand out without anyone having to read closely.
What you will learn. By the end of this lesson you'll be able to do three things. First, write an Arcade expression that colors an indicator by thresholds and adds a comparison line, like "plus 674 versus yesterday". Second, style the rows of a list so that high priority service requests stand out, and add computed text such as how many days a request has been open. Third, style individual cells in a table, for example highlighting large water mains that have broken. We'll also test the threshold logic in Python first, which is a handy habit when the rules come from a manager's email and have to be exactly right.
Arcade in one minute. Arcade is Esri's small expression language. Think of it as a spreadsheet formula that can also use if statements, variables and dates. It runs across ArcGIS Online, in pop-ups, labels, Field Maps and dashboards. Each place where Arcade runs is called a profile, and a profile decides which ready-made variables you get. In the dashboard advanced formatting profile, the key one is dollar datapoint, which holds the values of the thing being drawn: the statistic behind an indicator, or one feature in a list or table. Indicators also get dollar reference, the comparison value. When you open the expression editor, the variables panel lists the exact field names you can use, so copy them from there instead of guessing.
How advanced formatting works. Here's the flow. The dashboard queries your layer, then hands each data point to your expression. For an indicator that happens once; for a list or table it happens once per row. Your expression reads the values, makes decisions, and returns a dictionary. A dictionary is simply a set of named slots, like a form with labeled boxes: backgroundColor goes in one box, middleText in another. The dashboard then fills its drawing from those boxes. That's the whole idea. You never draw anything yourself; you just return the right names with the right values, and any key you leave out keeps its normal setting.
Worked example: outage indicator. Let's build the storm night indicator. At the top we store our three colors in variables, red, amber and green, so each color lives in one place. We read today's open outage count and the reference value, which here is yesterday's count. We start with green and the word NORMAL. If more than 500 are open, the card becomes red and says SEVERE; otherwise, if more than 200 are open, it becomes amber and says HIGH. On amber we switch to dark text, because white text on amber is hard to read on a wall screen. Order matters: check the biggest threshold first. Then we return the dictionary. The top text carries the level as a word, so nobody has to rely on color alone. The Text function formats numbers, so 1284 shows as 1,284. The format with a semicolon has two halves, one for positive and one for negative numbers, which gives us a proper plus or minus sign. On a bad night the whole card turns red, reads SEVERE and says plus 674 versus yesterday.
Test the rules in Python first. Is exactly 500 outages amber or red? Rules written in meetings are fuzzy at the edges, so test the edges. This short Python function mirrors our Arcade logic, and we run it on four cases, including the boundary values 200 and 500. Notice that 200 stays green and 500 stays amber, because we used "greater than", not "greater than or equal to". If the operations manager expected 500 to be red, you've just caught that before it went live. It takes two minutes, and it's the same habit you'd use testing any business rule: pick the values right on the line and confirm the result by eye.
Lists: flag urgent service requests. Now a list of three one one service requests: potholes, water leaks, downed signs. The list expression runs once for each row. We give high priority rows a soft red background and medium ones a soft yellow, and leave the rest with an empty string, which means use the default. Then comes the useful part: the attributes dictionary. It lets you compute new values that aren't stored in the layer. Here DateDiff measures how many days the request has been open. In the list's line item template you insert it with the placeholder shown in the last line: curly brace, expression slash age, curly brace. So each row now reads something like "Water leak, Elm Street, 4.5 days open", without anyone adding a field to the layer.
Tables: style single cells. Tables go one level deeper. You can style the whole row and single cells in the same dictionary. Keys at the top level, like backgroundColor here, style the entire row, so every break that is still open gets a soft yellow row. Then the cells dictionary has one entry per field you want to change. In this table of water main breaks, the diameter cell shows the size with "in" after it, and gets a red background when the pipe is 12 inches or larger, because big mains mean big outages. The status cell shows its text in capitals, red when the break is still open and green when it's closed. IIf is Arcade's one-line if: a condition, the value when true, and the value when false. Fields you don't mention in cells keep their normal look.
Keep it readable and consistent. A few habits keep these expressions easy to live with. Put your colors in variables at the top, as the outage indicator did with red, amber and green, so a later change happens in one place and every element stays consistent. Use soft backgrounds with dark text for rows; saturated red behind every row is exhausting on a wall screen during a long storm response. Always pair color with a word, like OPEN or SEVERE, or an icon, because some viewers can't tell red from green. And format numbers with the Text function, so executives read 1,284 rather than 1284 point zero. The next lessons build on these habits.
Common mistake: empty values. The most common mistake is forgetting empty values. In real service request data, some rows have no opened date or no priority, and a pipe record may have no diameter. Arcade usually doesn't stop on an empty value; it quietly carries on. In math an empty value counts as zero, and in a text join it becomes nothing, so a pipe with no diameter can read "0 in" or just " in", and a request with no opened date shows a blank age. If the expression does hit an error, that row loses its styling and falls back to the default look. Guard every field with DefaultValue, for example DefaultValue of the diameter field, zero, or check it with IsEmpty before you use it. The second trap is a misspelled key. If you write bgColor instead of backgroundColor, nothing fails; the dashboard simply ignores it. So when a color doesn't show up, check the spelling first.
Recap. Let's recap. Advanced formatting is an Arcade expression that reads dollar datapoint and returns a dictionary, and the dashboard styles the element from it. Indicators get colors and text lines plus dollar reference for comparisons; lists get row colors and computed attributes; tables get row colors and per-cell display text and colors through the cells dictionary. And you've got two safety habits: test your thresholds right at the boundaries, and guard every field against empty values. With those, your dashboard tells people what matters at a glance, instead of making them read every number.
Exercise. Here's your task before the next lesson. Take a layer of incidents, either a traffic incidents or service requests layer from Living Atlas, or one from your own organization. Build an indicator that turns green, amber or red using two thresholds you choose, and show the change against a reference value in the bottom text. Then add a list of the same incidents, highlight one important category with a soft background, and add an attribute showing hours since each incident was reported. Test your thresholds at the exact boundary values, and make sure one empty field doesn't break any rows.
ملخص الدرس
- مشاهدة الفيديو
- Advanced formatting returns a dictionary of styles
- Indicators, lists and tables each have their own keys
- Test thresholds at the edges and guard empty values