0%

The Complete Guide to
Data & Widgets in EB

From connecting your first data source to building multi-widget dashboard architectures that handle real-world disaster operations at scale.

Beginner — 7 lessons Intermediate — 6 lessons Advanced — 5 lessons

What's inside

Connecting Data to Widgets

Every EB app starts with data. Get the data model wrong, and you'll fight the tool the entire build. Get it right, and everything clicks.

Lesson 0

The data model — how EB connects to data

Experience Builder has a fundamentally different data model from Web AppBuilder or ArcGIS Dashboards. Understanding this model is the single most important thing you can do before building anything.

In Dashboards, you add a layer to a widget and the widget owns that connection. In EB, data flows through a centralized data source system. Widgets don't own data — they subscribe to it.

Think of it this way

Dashboards is like giving each employee their own copy of a spreadsheet. EB is like putting one spreadsheet on a shared drive and having everyone read from it. When the spreadsheet updates, everyone sees the change simultaneously.

There are three core concepts you need to internalize:

1.

Data Source

The original connection to your data — a Web Map, Feature Layer, CSV, or GeoJSON. Added once in the Data panel, shared by all widgets.

2.

Data View

A filtered or sorted "lens" on a data source. Same data, different perspective. Multiple widgets can share one data view, or each can have its own.

3.

Output Data Source

Data that a widget produces as output — like "the features the user selected on the map." Other widgets can subscribe to this output.

Feature Layer
Data Source
Map Widget
Subscribes
Selected Features
Output DS
List Widget
Subscribes
Key mental model

Data flows one direction: from Data Sources, through Widgets, out as Output Data Sources, and into other Widgets. Understanding this flow is how you build apps that don't break when users interact with them. If you're fighting EB, you're probably fighting this flow.

ConceptWhat it isExample
Data SourceConnection to external dataA Feature Layer of shelter locations
Data ViewFiltered lens on a data sourceOnly open shelters (status = 'Open')
Output Data SourceWidget-generated dataFeatures the user clicked on the map
Use Data SourceA widget's connection configMap widget connected to Web Map DS

Quick check: In EB's data model, who "owns" the data?

Lesson 1

Adding data sources

The Data panel (left sidebar, database icon) is where every data connection starts. You can add four types of data sources, and each has different trade-offs.

Source TypeBest ForLimitations
Web MapMost apps. Brings all layers, popups, symbology, and labels with it.Can't exclude individual layers (they all come in). Popup config travels with the map.
Feature LayerWhen you need a layer without a map, or a layer that isn't in your web map.No symbology — widgets get raw data only. You'll configure display in each widget.
CSVQuick prototyping, static reference data, lookup tables.No editing. Data is embedded in the app — no live connection. Max ~10MB practical limit.
GeoJSONExternal API data, developer-generated content.Same as CSV — static, embedded, no editing. Must be valid GeoJSON.
1
Open your EB app in the builder and click the Data icon in the left sidebar (looks like a cylinder/database)
2
Click + Add data. Choose your source type. For Web Map, search your org or paste the item ID.
3
Once added, expand the data source to see its layers. Each layer becomes a separate data source widgets can connect to.
4
Hover over any layer and click the settings gear to configure default sort, filter, or refresh interval.
Common mistake

Adding the same Feature Layer both directly AND inside a Web Map creates two separate data sources. Widgets connected to one won't react to filters on the other. Pick one source and stick with it. If your layer is in the Web Map, use the Web Map version.

Web Map vs Feature Layer — when to choose which
  • If your app has a Map widget: add the Web Map. You get symbology, labels, popups, and all layers in one shot.
  • If you only need a List or Table (no map): add the Feature Layer directly. Less overhead.
  • If you need a layer that isn't in your web map: add it as a standalone Feature Layer alongside the Web Map.
Try it yourself

Create a new EB app. Add a Web Map that has at least two layers. Then add one standalone Feature Layer. Open the Data panel and notice how the Web Map shows its layers nested underneath it, while the standalone layer is at the top level.

Lesson 2

List widget

The List widget is EB's workhorse. It turns any data source into a scrollable, clickable, searchable list of items. Think of it as a repeating template — you design one item, and the List stamps it out for every record in your data.

Think of it this way

The List widget is like a mail merge. You design the letter template once, and the software fills in each recipient's name, address, and details. Each "letter" in the List is called a list item, and you design it using child widgets (Text, Image, Button).

1
Drag a List widget onto your canvas. It will show placeholder items.
2
In the Content tab, click Select data and choose your data source (e.g., a Feature Layer from your Web Map).
3
Click Template to enter the template designer. This is where you design what each list item looks like. Drag Text, Image, or Button widgets inside.
4
Select a Text widget inside the template and use the Dynamic content button (curly braces icon) to insert field values like {NAME} or {STATUS}.
5
Under Arrangement, choose list direction (vertical/horizontal) and items per page.
6
Under Tools, enable Search (pick the field to search), Sort, and Filter if needed.
SettingWhat it controlsRecommendation
Items per pageHow many items load at once10-20 for most apps. More causes slow initial load.
Scroll typePagination vs infinite scrollPagination for data exploration. Infinite scroll for browsing.
Item heightFixed vs auto heightFixed for uniform layouts. Auto if content varies significantly.
Selection modeSingle vs multi-selectSingle for "click to see details." Multi for "select items to export."
Key concept: the template is not a widget

The List template is a container layout that repeats. Child widgets inside the template automatically get the context of the current record. When you put a Text widget inside a List template and bind it to {NAME}, each list item shows a different name. You don't need to set up 50 text widgets — one template handles all records.

Pagination trap

If your list shows 1,000 features but you set "items per page" to 1,000, EB will try to render all 1,000 DOM elements at once. This destroys performance on mobile. Use 10-20 items per page and let users paginate or scroll. The List widget handles this efficiently with lazy loading.

Lesson 3

Table widget

The Table widget shows your data as rows and columns — exactly like a spreadsheet. It's the fastest way to give users a way to browse, sort, filter, and export data. Less design flexibility than List, but faster to set up and better for data-heavy workflows.

1
Drag a Table widget onto your canvas.
2
Click Select data and choose your data source.
3
Under Columns, click to show/hide fields, drag to reorder, and click each column to set display name, width, and formatting.
4
Under Tools, enable: Search (pick which fields), Select (row selection mode), Filter, Sort, and Export (CSV download).
5
Set Row height and Rows per page to control density. For operational dashboards, smaller rows and more per page works well.
1.

Use Table when...

Users need to compare values across records, sort by multiple columns, export data, or see many fields per record.

2.

Use List when...

You want visual design control, images, custom layouts, or when the data is best shown as cards rather than rows.

Table + Map interaction
  • When a user clicks a row, the Table can zoom the map to that feature. Enable this in the Table's Action tab.
  • When a user selects features on the map, the Table can highlight those rows — if both use the same data source.
  • The Table automatically generates an output data source (selected rows) that other widgets can consume.
Export gotcha

The Table's CSV export only exports currently visible/filtered rows, not the entire dataset. If the user has a filter active, the export reflects that filter. This is actually useful — but users will be confused if they don't realize it. Add a Text widget near the Table showing the current record count so users know what they're exporting.

Quick check: Which widget gives you more visual design control per item?

Lesson 4

Filter widget

The Filter widget is how you let users narrow down data without writing code. It builds SQL WHERE clauses behind the scenes and applies them to one or more connected widgets. There are two modes, and choosing the wrong one is the most common beginner mistake.

1.

SQL Expression Mode

You define the exact SQL clause. User sees a clean dropdown or input. Best for controlled, predictable filtering.

2.

Simple Mode

Users build their own filter by choosing field, operator, and value. More flexible, but can confuse non-technical users.

1
Drag a Filter widget onto your canvas.
2
Click New filter. Choose your data source — this determines which fields are available.
3
Choose SQL expression builder for controlled filtering. Build your clause: e.g., STATUS = 'Open'. Check "Ask for value" to let the user pick from a dropdown.
4
Under Filter arrangement, choose whether filters appear as pills, dropdowns, or a panel.
5
The Filter automatically applies to all widgets using the same data source. No manual wiring needed — that's the power of EB's centralized data model.
This is the whole point of EB's data model

Because widgets subscribe to shared data sources, a single Filter widget can update a Map, a List, a Table, and a Chart all at once. You don't connect the Filter to each widget — the Filter modifies the data source, and every widget subscribed to that source automatically refreshes. This is fundamentally different from Dashboards, where you wire each connection manually.

SQL Expression Examples
-- Single value filter (dropdown)
STATUS = '${value}'

-- Multi-value filter (checkboxes)
REGION IN ('${value}')

-- Range filter (slider)
POPULATION >= ${value1} AND POPULATION <= ${value2}

-- Date range filter
CREATED_DATE >= '${value1}' AND CREATED_DATE <= '${value2}'

-- Combined AND clause
STATUS = 'Open' AND CAPACITY > 50
Filter scope trap

If you add a Filter that targets a Web Map data source, it filters all layers in that Web Map that have the matching field name. If your shelter layer and your county layer both have a "NAME" field, filtering by NAME affects both. Solution: use more specific field names, or target individual layers instead of the Web Map root.

Try it yourself

Add a Map, a List, and a Filter all connected to the same Feature Layer. Create a SQL filter for one field (like STATUS or TYPE). Apply the filter and watch both the Map and the List update simultaneously. This is the fundamental EB interaction pattern.

Lesson 5

Chart widget basics

The Chart widget visualizes your data as bar, line, pie, or scatter charts. It connects to the same data sources as everything else, so filters applied elsewhere automatically update the chart. This is what makes EB dashboards genuinely interactive.

Chart TypeBest ForKey Setting
BarComparing categories (shelters by region, cases by type)Category field + value field + aggregation (count, sum, avg)
LineTrends over time (daily case count, monthly openings)Date field on X axis + value field + aggregation
PieProportions of a whole (% by status, % by category)Category field + count or sum aggregation
ScatterCorrelation between two numeric fieldsX field + Y field, both numeric. No aggregation.
1
Drag a Chart widget onto your canvas. Choose chart type (bar, line, pie, scatter).
2
Click Select data and choose your data source.
3
Set the Category field (what's on the X axis or pie slices) and the Value field (what's measured).
4
Choose the aggregation: Count, Sum, Average, Min, or Max. "Count" is most common — it counts how many records are in each category.
5
Under Appearance, customize colors, labels, legend position, and axis formatting.
Aggregation explained
  • Count — How many records per category. "How many shelters are in each state?"
  • Sum — Total of a numeric field per category. "Total capacity by region."
  • Average — Mean of a numeric field. "Average response time by chapter."
  • Min / Max — Lowest or highest value per category. "Earliest opening date by region."
Chart + Filter interaction

When a Filter widget changes the data source, the Chart re-aggregates from the filtered data. This means your "Shelters by Region" chart will show different numbers depending on what status filter is active. This is usually what you want — but if you need a chart that always shows all data regardless of filters, you must connect it to a separate data source or a data view that isn't affected by the filter. More on this in Lesson 7.

Quick check: You want to show "total shelter capacity by state." What aggregation do you use?

Lesson 6

Text widget with data

The Text widget isn't just for static labels. When connected to a data source, it becomes a dynamic display that shows field values, counts, and even simple Arcade calculations. This is how you build info panels, summary headers, and detail views.

1
Drag a Text widget onto your canvas.
2
Click Select data and connect to your data source.
3
Click inside the text editing area. Use the Dynamic content button (curly braces icon in the toolbar) to insert field values.
4
Available dynamic content includes: {FIELD_NAME} for field values, {OBJECTID} for the record ID, and statistic values like record count.
5
For statistics (count, sum, average), use the Statistic type in the dynamic content picker. This calculates across all records, not just one.
Three modes of dynamic text
  • Single record — shows data from one feature (e.g., the selected shelter's name). The Text widget displays data from the "current" record — whatever is selected or first in the data.
  • Statistics — shows aggregated values across all records (e.g., "Total shelters: 47"). Uses the built-in statistic functions.
  • Arcade expression — write custom logic using the Advanced Formatting panel. This unlocks everything from conditional text to HTML-formatted content.
Simple Arcade in Text Widget
// Show a status badge with dynamic text
var status = $datapoint.STATUS
var name = $datapoint.SHELTER_NAME

if (status == "Open") {
  return name + " — Currently OPEN"
} else {
  return name + " — Closed"
}
Text widget inside a List

When a Text widget is inside a List template, $datapoint automatically refers to the current list item's record. Outside a List, $datapoint refers to the first record in the connected data source, or the selected record if a selection exists. This context-sensitivity is what makes Text widgets so versatile.

Try it yourself

Add a Text widget connected to a Feature Layer. Insert a dynamic field value (like NAME). Then add a second Text widget and use the Statistics dynamic content to show the total record count. Put both above your Map — you now have a simple dashboard header that says "Showing 47 shelters" and updates when filters change.

Widget Orchestration

You know the individual widgets. Now learn how to make them talk to each other — and how to avoid the circular dependency traps that break most first-time dashboard builds.

Lesson 7

Data views vs output data sources

This is the concept that trips up the most people. Esri's docs use both terms loosely, but they are fundamentally different things, and confusing them is the root cause of 90% of "my widgets aren't connected" bugs.

1.

Data View

A pre-defined filter or sort on a data source. You create it in the Data panel. It always exists, whether the user does anything or not. Think of it as a "saved view."

2.

Output Data Source

Data produced by a widget at runtime. It only exists when the user interacts — selecting features on a map, filtering rows in a table. It's dynamic and ephemeral.

Think of it this way

A data view is like a saved SQL query that always returns the same filtered results. An output data source is like a "selected items" shopping cart — it's empty until the user puts things in it, and it changes every time they interact.

AttributeData ViewOutput Data Source
Created byYou (in the Data panel)Widgets (automatically, at runtime)
Exists whenAlways — even before user interactionOnly after user interaction (selection, filter)
Changes at runtimeNo (unless a Filter widget targets the same source)Yes — every time the user interacts
Use case"Only show open shelters in the list""Show details for whatever the user just clicked"
Found inData panel, under the parent data sourceWidget settings, "Output data source" section
When to use each
  • Use a data view when you want a widget to always show a subset: "This List only shows shelters where STATUS = 'Open'."
  • Use an output data source when you want widgets to react to user interaction: "When someone clicks a feature on the Map, show its details in the side panel."
  • Use both together for powerful chains: a Map's output data source feeds a List, and the List uses a data view to further filter that output.
Feature Layer
Data Source
Data View
status = Open
Map Widget
Output DS
selected features
List Widget
detail view

Quick check: A data view is created by _____ and an output data source is created by _____.

Lesson 8

Filter-Map-List-Chart chains

This is the cascade architecture — the pattern behind every production EB dashboard. A single user action (choosing a filter value) triggers a cascade of updates through all connected widgets. Getting this right is the difference between a demo and a deployable app.

Filter
user picks "Open"
Data Source
WHERE status=Open
Map + List + Chart
all update

The cascade works because all widgets share the same data source. When the Filter modifies that data source's active query, every subscriber re-renders. But there are rules:

Cascade rules
  • Same data source = automatic sync. If Filter, Map, List, and Chart all connect to the same data source, they sync automatically. No wiring needed.
  • Different data sources = no sync. If your Chart connects to a standalone Feature Layer but your Filter targets the Web Map version of the same layer, they won't sync. This is the most common "why isn't my chart updating?" bug.
  • Output data sources add a second cascade. User clicks a feature on the Map → Map produces an output DS → a "detail" List subscribes to that output DS. Now you have two cascades: filter-based (data source level) and selection-based (output DS level).
1
Start with your data sources. Add the Web Map (or Feature Layer). Make sure every widget that needs to sync connects to the same data source.
2
Add a Filter widget targeting that data source. Test it — all connected widgets should update when you apply a filter.
3
Add a Map widget. Enable the "Select" tool in the Map's toolbar. When users select features, the Map creates an output data source.
4
Add a List (or Table) and connect it to the Map's output data source instead of the main data source. Now this List shows only selected features.
5
Add a Chart connected to the same data source as the Filter. The chart will react to both filters and the overall data changes.
The double-cascade trap

Be careful connecting a List to the Map's output data source AND applying a Filter. The Filter changes the data source, which changes what's on the Map, which changes what can be selected. If your List is connected to the output data source, it might show "no data" after a filter change because the previous selection is now invalid. Solution: clear the selection when filters change (using the Map's action settings), or connect the List to the data source directly.

Build the canonical dashboard

Build this exact layout: Filter (top) → Map (left, 60% width) + List (right, 40% width, connected to same data source) + Chart (bottom, full width, same data source). Apply a filter — everything updates. Click a feature on the Map — the List highlights that row. This is the production pattern you'll use for 80% of EB dashboards.

Lesson 9

Edit widget

The Edit widget turns your EB app from a read-only viewer into a data entry tool. Users can create new features, update existing ones, and delete records — directly from your app, with no AGOL login required (if the layer allows anonymous editing).

Before you start

The Edit widget requires your Feature Layer to have editing enabled. In ArcGIS Online, go to the layer's Settings tab and check "Enable editing." Choose which operations to allow: Add, Update, Delete. If the layer is view-only, the Edit widget will show an error.

1
Ensure your Feature Layer has editing enabled in AGOL (Settings → Editing).
2
Drag an Edit widget onto your canvas. Connect it to a Map widget — the Edit widget works with features on the map.
3
Under Edit settings, choose which layers are editable and which operations are allowed (Add, Update, Delete).
4
Under Fields, configure which fields appear in the edit form, their labels, and whether they're required. You can hide system fields like OBJECTID and GLOBALID.
5
Enable Snapping if users need to place features precisely (aligning to existing vertices or edges).
6
Under Validation, set field-level rules: required fields, value ranges, domain enforcement.
Edit widget field types
  • Text fields — standard text input or text area for longer content
  • Number fields — numeric input with optional min/max validation
  • Date fields — date picker (the widget handles timezone conversion)
  • Coded value domains — automatically rendered as dropdowns with the domain values
  • Attachments — photo/file upload if the layer has attachments enabled
Edit workflows in practice

The typical edit flow: user clicks a feature on the Map → Edit widget shows the attribute form → user modifies fields → clicks Save → the feature is updated in the Feature Layer → all other widgets (List, Table, Chart) automatically refresh because they share the same data source. For new features: user clicks the "Add" button → clicks on the map to place the point → fills in the form → saves.

Security considerations

If your Feature Layer allows anonymous editing, anyone with the app URL can modify data. For production apps, either: (1) require AGOL login to edit, (2) use the layer's editing settings to restrict who can edit, or (3) use ArcGIS Workflow Manager for approval-based editing. Never expose unrestricted editing on sensitive operational data.

Lesson 10

Near Me widget

The Near Me widget lets users draw a point or area on the map and find features within a search radius. This is critical for disaster operations — "What shelters are within 10 miles of this address?" or "How many damage assessments are in this county?"

1
Drag a Near Me widget onto your canvas. It requires a connected Map widget.
2
Under Analysis settings, set the search method: proximity (distance from point) or area (within a drawn polygon).
3
Set the default search distance and max distance. For disaster ops, 5-25 miles is typical for shelter searches.
4
Choose which layers to search. You can search multiple layers — shelters, distribution points, volunteer staging areas — in one operation.
5
Configure the results display: which fields to show, how to sort (by distance is most useful), and whether to show the count.
Near Me + geocoding
  • Enable the Search tool on the Map widget so users can type an address (geocoding) before using Near Me.
  • The Near Me widget can use the map's center point, a clicked point, or a geocoded address as the search origin.
  • Results are sorted by distance from the search point — nearest first.
1.

Disaster use case: Shelter Finder

User enters their address → Near Me shows shelters within 10 miles → sorted by distance → user clicks one to see details and driving directions.

2.

Disaster use case: Damage Assessment

User draws a polygon around a neighborhood → Near Me counts damage reports within that area → grouped by severity level.

Performance consideration

Near Me performs a spatial query against your Feature Layer. If the layer has 100,000+ features, large search radii (50+ miles) can be slow. Use the maxRecordCount setting on the layer and keep search distances reasonable. For very large datasets, consider creating a pre-computed "nearest facility" field in your data instead of relying on runtime spatial queries.

Lesson 11

Query widget and dynamic filtering

The Query widget is the Filter widget's more powerful sibling. While Filter modifies the data source globally (affecting all connected widgets), the Query widget lets you build complex, multi-step queries with AND/OR logic, spatial filters, and the ability to target specific widgets rather than the entire data source.

1.

Filter Widget

Simple. Modifies the shared data source directly. All connected widgets update. Best for global app-wide filtering.

2.

Query Widget

Advanced. Creates its own output data source with query results. You control which widgets consume it. Best for targeted, multi-criteria searches.

1
Drag a Query widget onto your canvas.
2
Click New query and select a data source.
3
Build your query using the SQL builder. Add multiple clauses connected with AND/OR. For each clause, choose whether to use a fixed value or "Ask for value" (user input).
4
Optionally add a spatial filter: "within the map extent," "within a drawn geometry," or "near a point."
5
Configure the results panel: which fields to display, sort order, and what happens when a user clicks a result (zoom to feature, show popup, etc.).
6
The Query widget creates an output data source with the results. Connect other widgets (Table, Chart, List) to this output DS for targeted displays.
Query: Multi-criteria shelter search
-- User-facing query with three criteria
-- "Ask for value" on STATUS and REGION
-- Fixed value on CAPACITY

STATUS = '${user_status}'         -- Dropdown: Open/Closed
  AND
REGION IN ('${user_regions}')    -- Multi-select checkboxes
  AND
CAPACITY >= 25                  -- Fixed: only shelters with 25+ capacity
Filter vs Query — decision guide
  • Need all widgets to react to one filter? Use Filter widget.
  • Need complex AND/OR logic with multiple clauses? Use Query widget.
  • Need spatial filtering (within extent, near point)? Use Query widget.
  • Need the results to feed a specific widget without affecting others? Use Query widget + its output data source.
  • Need both? Use a Filter for global narrowing, then a Query for detailed search within the filtered data.
Lesson 12

Conditional visibility with data

Conditional visibility lets you show or hide entire widgets based on data conditions. This is how you build apps that adapt — showing an "emergency alert" banner only when there's an active disaster, or hiding the edit panel when there's nothing selected.

1
Select the widget (or container) you want to conditionally show/hide.
2
In the Action tab, find the Visibility section (or on some widgets, it's under the widget's settings gear).
3
Set a trigger: "When data source has records" or "When expression is true." For data-based visibility, the most common trigger is "data source record count."
4
For expression-based triggers, write an Arcade expression that returns true (show) or false (hide).
Visibility: Show panel only when features are selected
// Connect to the Map's output data source (selected features)
// Show the detail panel only when something is selected

var count = Count($datapoints)
return count > 0
Common conditional visibility patterns
  • Detail panel — show a side panel only when a feature is selected on the map (output DS has records)
  • No-data message — show "No results found" text when a filter returns zero records
  • Emergency banner — show an alert banner when a "disasters" data source has records where STATUS = 'Active'
  • Role-based content — show edit tools only for authenticated users (combine with AGOL identity checks)
  • Mobile adaptation — use viewport width expressions to show/hide widgets at different screen sizes
The empty-state problem

When your Map has nothing selected, widgets connected to its output data source show "No data." This is ugly. Instead, create two versions of your detail panel: one that shows "Click a feature to see details" (visible when output DS is empty) and one that shows the actual data (visible when output DS has records). Toggle between them using conditional visibility. This pattern is called empty state handling and it's the mark of a polished app.

Quick check: You want to show a "detail" panel only when a user selects something on the map. What data source do you use for the visibility condition?

Production Architecture

You've built dashboard prototypes. Now learn the patterns that survive contact with real users, real data volumes, and real operational pressure.

Lesson 13

Multi-widget dashboard architecture

When you have 8+ widgets all sharing data sources, you need an architecture — not just a collection of widgets. The two patterns that work at scale are hub-and-spoke and parallel pipelines.

1.

Hub-and-Spoke

One central data source feeds all widgets. A Filter widget modifies the hub, and all spokes update. Simple, predictable, and works for 80% of dashboards.

2.

Parallel Pipelines

Multiple data sources, each feeding their own widget chain. Use when you need widgets that DON'T sync — e.g., a "comparison mode" with two independent maps.

Hub-and-spoke architecture

The hub is your primary data source (usually a Web Map with its layers). All widgets connect to this hub. Filter and Query widgets modify the hub. Every widget downstream reacts. This is the default pattern — use it unless you have a specific reason not to.

Web Map
hub
Filter
Map + List + Chart + Table
all sync
Avoiding circular dependencies

A circular dependency happens when Widget A's output feeds Widget B, and Widget B's output feeds Widget A. Example: a Map selects features that populate a List, and clicking a List item zooms the Map — which changes the selection — which updates the List — which triggers another zoom. The result: infinite loops, frozen UI, or unpredictable behavior.

  • Rule 1: Data should flow in one direction. Draw your data flow on paper before building. If you see a cycle, redesign.
  • Rule 2: Use "actions" (zoom, pan) for UI effects, not data source modifications. A List clicking to zoom the Map is fine — but a List changing the Map's data source is dangerous.
  • Rule 3: If two widgets both need to drive each other, introduce a third widget (like a Button or Filter) that explicitly controls both.
Architecture checklist for complex dashboards
  • Draw the data flow diagram before building. Every arrow should go one direction.
  • Identify your hub data source. All global filters target this source.
  • Identify which widgets need independent data (comparison panels, reference data, summary statistics that shouldn't be filtered).
  • Use data views for "always-filtered" subsets. Use output data sources for "user-driven" subsets.
  • Test the cascade: apply a filter, check every widget updates. Select a feature, check only the right widgets update.
Lesson 14

Handling large datasets

ArcGIS Feature Layers have a maxRecordCount — the maximum number of features returned per query. The default is 1,000 (AGOL) or 2,000 (Enterprise). If your layer has 50,000 features and a widget queries without pagination, you only get the first 1,000. This is the single most common "where's my data?" problem in EB.

The 1,000 / 2,000 limit

When you see a List showing exactly 1,000 items out of 50,000, or a Chart aggregation that seems wrong, or a "record count" text that tops out at 1,000 — you've hit the maxRecordCount limit. The widget isn't broken; it's only seeing partial data.

ApproachHow it worksWhen to use
Pagination (List/Table)List and Table widgets paginate automatically — they request pages of records. Each page = one query up to maxRecordCount.Default for List/Table. Works well up to ~50K records.
Server-side filteringApply filters before data reaches the client. The WHERE clause runs on the server, returning only matching records.Always. Reduce the dataset before rendering. A filter that takes 50K → 500 records makes everything fast.
Increase maxRecordCountIn AGOL, go to the layer's Settings → change "Max Record Count" (up to 32,000 on AGOL, higher on Enterprise).When widgets need all records for accurate aggregation (Charts, Statistics).
Feature Layer ViewsCreate a View Layer in AGOL with a permanent WHERE clause. The view only contains the subset you need.When your app only needs a geographic or attribute subset of a large dataset.
Materialized views / summary tablesPre-aggregate data in a separate table. Instead of querying 100K individual records, query 50 summary rows.For charts and statistics on very large datasets (100K+).
The aggregation accuracy problem

If your Chart widget does a "count by region" aggregation on a 50,000-record layer with maxRecordCount = 1,000, it only aggregates the first 1,000 records. The chart looks right but shows wrong numbers. This is insidious because there's no error message — just incorrect data. Solutions: increase maxRecordCount for that layer, use a pre-aggregated summary table, or use a server-side group-by query (available in EB's advanced data source settings).

Performance tiers
  • < 5,000 records — Everything works out of the box. No special handling needed.
  • 5,000 - 25,000 records — Use pagination on Lists/Tables. Ensure Charts have adequate maxRecordCount. Apply default filters where possible.
  • 25,000 - 100,000 records — Use server-side filtering aggressively. Create Feature Layer Views for subsets. Consider pre-aggregated summary tables for Charts.
  • 100,000+ records — Pre-aggregation is mandatory for accurate statistics. Use Feature Layer Views. Consider breaking the app into multiple focused views instead of one mega-dashboard.

Quick check: Your chart shows "Total shelters: 1,000" but you know there are 8,000 in the dataset. What's the most likely cause?

Lesson 15

Dynamic data sources with Arcade

Arcade isn't just for formatting text. In EB's advanced settings, you can use Arcade to create computed fields (virtual columns that don't exist in the actual data), dynamic labels, and conditional data transformations that happen at query time.

What Arcade can do with data sources
  • Computed fields — Create virtual fields from expressions. Example: a "days since last update" field computed from a date field, or a "full address" field concatenated from street, city, state, zip.
  • Conditional classification — Turn numeric values into categories. Example: capacity 0-25 = "Small", 26-100 = "Medium", 101+ = "Large".
  • Cross-field calculations — Combine multiple fields: occupancy rate = current / capacity * 100.
  • Dynamic labels in Map — Arcade expressions in the Web Map's label settings create labels that change based on data values.
Computed field: Occupancy classification
// Use in a data source's "expression" field or in a widget's Arcade
var current = $datapoint.CURRENT_OCCUPANCY
var capacity = $datapoint.MAX_CAPACITY

if (capacity == 0 || capacity == null) {
  return "Unknown"
}

var rate = Round((current / capacity) * 100, 1)

if (rate >= 90) { return "Critical" }
if (rate >= 75) { return "High" }
if (rate >= 50) { return "Moderate" }
return "Low"
Computed field: Days since last update
var lastUpdate = $datapoint.LAST_UPDATED
var now = Now()

if (IsEmpty(lastUpdate)) {
  return "Never updated"
}

var days = DateDiff(now, lastUpdate, "days")

if (days < 1) { return "Today" }
if (days < 2) { return "Yesterday" }
return Round(days, 0) + " days ago"
Computed fields are client-side

Arcade computed fields run in the browser, not on the server. They can't be used in server-side queries or filters — only in display. If you need to filter by a computed value (like "show only Critical occupancy shelters"), you need to either: (1) add the computed field to the actual layer using a Python script, or (2) use the Arcade expression within the Filter widget's SQL builder. Option 1 is more reliable for production apps.

Try it yourself

Pick a Feature Layer with a date field. Add a Text widget, connect it to that layer, and write an Arcade expression that returns "X days since last update" using DateDiff. Then add a second Text widget that shows the occupancy rate classification (Critical/High/Moderate/Low) based on two numeric fields. You now have dynamic computed data without modifying the original layer.

Lesson 16

Real-world patterns: disaster operations dashboards

After building dozens of operational dashboards for Red Cross disaster response, these are the patterns that survive contact with real users under real pressure. Every pattern here has been tested during actual disaster operations.

Pattern 1: The Operations Hub

Layout: Filter bar (top) + Map (left 60%) + Tabbed panel (right 40%) with List/Table/Chart tabs + Summary bar (bottom). Data: one Web Map with shelter, distribution, and volunteer layers. Filter targets the Web Map root — all layers filter simultaneously. The tabbed panel shows different views of the same filtered data. This pattern handles 3-5 operational layers and 10,000+ records comfortably.

Region Filter
Web Map
hub
Map + Tabbed Panel + Summary
Pattern 2: The Detail Drilldown

Layout: Map (full width, top half) + Detail panel (bottom half, initially hidden). User clicks a feature on the Map → detail panel appears (conditional visibility on output DS). Detail panel contains: name/status header (Text widget with Arcade), attribute table (Table widget connected to output DS), related records (List widget), and an Edit button. This is the pattern for field teams who need to view and update individual records.

Pattern 3: The Comparison Dashboard

Layout: Two side-by-side Maps, each connected to a different data view of the same data source. Left map shows "before" (data view filtered to a date range), right map shows "after." A shared Filter for region/area applies to the underlying data source, so both maps filter together. Separate Charts below each map show stats for their respective time periods. This uses parallel pipelines architecture.

PatternArchitectureBest For
Operations HubHub-and-spoke, single Web MapDaily ops monitoring, multi-layer dashboards
Detail DrilldownHub + output DS cascadeField data collection, record inspection
ComparisonParallel pipelines, data viewsBefore/after analysis, A/B comparison
Public FacingHub-and-spoke, read-only, mobile-firstShelter finders, resource locators
Data EntryMap + Edit widget, minimal UIDamage assessment, survey collection
Lessons from production
  • Always include a "reset filters" button. Users apply multiple filters and forget. A single button that clears all filters saves support tickets.
  • Show record counts. A Text widget showing "Displaying 47 of 1,234 shelters" tells users their filters are working and helps them trust the data.
  • Default to the most useful view. Pre-apply a "last 7 days" or "active only" filter on load. Users can broaden — but starting broad wastes their time.
  • Mobile matters. Disaster responders use phones in the field. Test at 375px wide. Stack columns vertically. Make touch targets large.
  • Auto-refresh for live data. Set the data source refresh interval (Data panel → layer settings) to 30-60 seconds for operational dashboards. Users forget to refresh manually.
Lesson 17

Debugging data connections

When widgets show "No data" or display wrong information, the problem is almost always in the data connection — not the widget itself. Here's a systematic approach to debugging every data issue you'll encounter in EB.

The 5-step debugging protocol
  • Step 1: Check the data source. Open the Data panel. Is the data source present? Does it show a record count? If it shows 0, the problem is the source itself (layer not shared, service down, invalid URL).
  • Step 2: Check the widget's connection. Select the widget. Look at "Data" or "Content" settings. Is it connected to the right data source? Is it connected to a data view or output DS when it should be connected to the main source (or vice versa)?
  • Step 3: Check active filters. Are there Filter widgets modifying the data source? Clear all filters and check if data appears. A filter that's too restrictive returns zero records.
  • Step 4: Check field names. If a dynamic text shows blank or a Chart shows nothing, verify the field name matches exactly (case-sensitive). Field names change when layers are republished.
  • Step 5: Check maxRecordCount. If numbers seem low or aggregations seem wrong, check the layer's maxRecordCount setting in AGOL.
SymptomLikely CauseFix
Widget says "No data"Wrong data source, or filter returning zero recordsCheck connection in widget settings. Clear all filters.
List shows items but no field valuesDynamic text references wrong field nameCheck field names in the Data panel. They're case-sensitive.
Chart shows wrong numbersmaxRecordCount limiting the aggregationIncrease maxRecordCount on the Feature Layer.
Filter doesn't affect MapFilter targets a different data source than the MapEnsure both use the exact same data source (not copies).
Widget works in builder but not publishedLayer sharing permissionsShare the layer with "Everyone" or the appropriate group.
Clicking Map doesn't update ListList connected to data source, not Map's output DSConnect List to Map's output data source for selection-driven updates.
Data appears staleNo auto-refresh configuredSet refresh interval in Data panel → layer settings.
Arcade expression returns blankNull values in referenced fieldsAdd null checks: if (IsEmpty(field)) return "N/A"
The dual-config trap (EB-specific)

Experience Builder has TWO configuration files: the Data tab (published/live app) and Resources → config/config.json (draft/editor). If you manually edit the published config (via AGOL Assistant or the REST API), your changes will work in the live app — but opening the EB editor and saving will overwrite your changes with the draft config. Always update the draft config first, then publish. This has bitten every EB developer at least once.

Browser DevTools for EB debugging
  • Open DevTools (F12) and go to the Network tab. Filter by "query" to see the actual REST API calls EB makes to your Feature Layers.
  • Look at the query URL parameters: where (the filter clause), outFields (requested fields), resultRecordCount (pagination).
  • If a query returns {"features":[]}, the WHERE clause is filtering out all records. Copy the WHERE clause and test it directly in the Feature Layer's REST endpoint.
  • Check the Console tab for Arcade errors. They show as "Expression evaluation error" with the expression ID and line number.

Quick check: Your Filter widget works on the Map but not on the Chart. What's the first thing to check?

You made it to the end!

You've gone from "how does data work in EB?" to multi-widget dashboard architectures, large dataset strategies, and production debugging protocols. These 18 lessons cover the full data-to-widget pipeline in Experience Builder. The patterns are modular — hub-and-spoke for most dashboards, parallel pipelines for comparisons, output data sources for selection-driven details. Combine them for any operational tool you need to build.