List
Renders a list of items from a Feature Service layer or a Web Map layer. Each item is designed visually with a block builder (text, date, image, gallery, badge, spacer, divider), and you can switch to a raw HTML/CSS editor for full control. Both modes live in a pop-out editor with a live preview. The list can also be filtered by a map's extent.
At a glance
| Type key | list |
| Default size | 3 × 12 (min 2 × 6) |
| Data source | A Feature Service layer or a Web Map layer |
| Emits | zoom / pan (on list:item-click, to a Map or 3D Scene) |
| Receives | filter (from a Map's map:extent-change) |
| Source | src/widgets/widgets/list/ |
Configuration
| Field | Type | Default | Purpose |
|---|---|---|---|
sourceKind | "feature-service" | "web-map" | "feature-service" | Whether the list is backed by a Feature Service layer or a Web Map layer. |
featureServiceId | string? | — | Feature Service item id backing the data (Feature Service mode only). |
featureServiceTitle | string? | — | Display title of the resolved service. |
featureLayerId | number? | — | Sub-layer id. |
featureLayerName | string? | — | Sub-layer name. |
webMapId | string? | — | Web Map item id selected as the source (Web Map mode only). |
webMapTitle | string? | — | Display title of the selected Web Map. |
webMapLayerId | string? | — | Operational-layer id of the chosen layer within the Web Map. |
webMapLayerName | string? | — | Web Map layer title. |
filterClauses | clause[] | [] | Attribute filter applied to the data source. Each clause is field operator operand; clauses join left-to-right with AND/OR into a SQL where. |
sortFields | sort[] | [] | Fields the results are ordered by, in precedence order. Each entry is { field, direction: "asc" | "desc" }, compiled into the query's orderByFields. Empty falls back to the mapped date field (newest first). |
titleField | string? | — | Field rendered as the item headline. |
summaryField | string? | — | Field rendered as the item summary. |
dateField | string? | — | Date field for ordering/display. |
dateFormat | string? | — | Legacy mapped-date pattern (migrated into the builder). Empty = localized. |
sourceField | string? | — | Legacy source label field (migrated into the builder). |
renderMode | "fields" | "template" | "fields" | Set to "template" once the builder or HTML editor is used. |
maxItems | number (1–200) | 25 | Maximum items shown. |
itemTemplate | string? | — | Compiled (or hand-written) HTML/CSS template. Supports {field}, {date:Field|pattern}, {icon:name} / {icon:lucide:name} / {icon:resource:path} / {icon:layer-symbol}, {image:Field}, and {attachment:first|first:thumb|all} tokens (an optional trailing pixel size, e.g. {attachment:all:120}, sizes the thumbnails). |
itemLayout | object? | — | Structured block layout authored in the builder; compiled into itemTemplate. |
customHtml | boolean | false | When true, the HTML editor owns itemTemplate and the builder no longer overwrites it. |
itemStyles | object | theme defaults | Per-state styling (default, hover, selected): optional background, textColor, borderColor. |
Item content
The config panel shows a compact summary of the current item design and a live preview. Click Open editor to launch the pop-out, which keeps the controls on the left and the live preview on the right. Authoring happens in one of two modes, switched with the Builder / HTML toggle inside the editor.
Visual builder
To get going quickly, pick a starter template from the gallery at the top of the builder. Each starter drops in a ready-made block layout and binds it to the best-matching fields in your layer:
- Headline — a title, summary, date, and category badge.
- Photo card — a banner image above a title and summary.
- Gallery — a title and summary with an attachment photo strip.
- Compact — a title with a date and category badge.
Field binding is best-effort: the starter looks for fields whose names hint at a title, summary, category, or date (and uses the first detected image field for photo blocks), falling back to placeholder text where it can't find a match. Choosing a starter replaces the current blocks, so use it as a starting point and then tweak the blocks below. You can always build from scratch instead.
Each item can carry an optional item icon rendered as its own column beside the block content. Pick an icon from the icon picker, place it in the first or last column, set its vertical alignment (top / center / bottom), and adjust its size (px), color (or leave the color unset to inherit the item's text color), and the spacing (px) between the icon and the content. The rest of what you build flows into the center content column.
The icon picker has up to three tabs:
- Icons — search the full Lucide library.
- Custom — upload your own image (PNG, JPG, SVG, …). It opens a crop dialog where you pan and zoom to a square, then it's stored as a 256×256 PNG resource on the workspace's portal item and added to the grid for reuse. Hover a custom icon to delete it. Custom icons require an open workspace, since they live with that workspace's item; uploads from the same workspace are available to every widget in it.
- Layer — shown only when the list references a feature layer. Uses the layer's own renderer symbol as the icon. For unique-value and class-breaks renderers each row shows the symbol its feature is drawn with, so the icon matches the map. Symbols come from the layer's metadata (no extra request) and resolve live, so author changes to the layer's symbology appear on the next load. When the list's source is a Web Map (see below), the symbol comes from that layer's web-map styling instead of the feature service default.
Choosing a source: Feature Service or Web Map
In the Data section, the Source type toggle picks where records come from:
- Feature Service — pick a service and one of its layers or tables.
- Web Map — pick a web map and one of its feature layers (including layers nested in group layers). The layer is resolved directly from the web map by its operational-layer id, so all data, fields, filters and queries behave exactly as they would in Feature Service mode, and the Layer item icon draws from the layer's authored web-map renderer (a feature layer can be styled differently inside a web map than in its source service). Renderer changes an author makes in the web map appear on the next load.
A web-map layer works whether the web map references its service by portal item or by URL — no portal item is required, since the loaded web map already carries the layer's service URL, fields, and renderer.
The Builder then assembles the content from ordered blocks:
- Text — a title, subtitle, body, or meta line bound to a field (or static
text). When bound to a field you can add free Before / After text that
wraps the value (e.g.
Owner: {name}or{dist} km). A font size (px) stepper fine-tunes the size in 1px increments; leave it blank to use the style preset's default. - Date — a date field formatted with a chosen pattern (or the localized default).
- Image — a picture sourced from a field (its value is an image URL) or a static URL. Choose a shape preset — inline (natural size), avatar (round), thumbnail (square), or banner (full-width) — and, for the shaped presets, how the image fits its box (cover, contain, or fill). Enable Show placeholder if missing to keep a neutral box when the image is absent or fails to load. For shaped presets the picture is then painted as a CSS background, so a broken or missing URL shows the placeholder tint instead of a broken-image icon.
- Badge — a pill bound to a field or static text.
- Gallery — image attachments from each feature. Choose All attachments (a wrapping thumbnail strip) or First attachment (a single block image), and set the image size (px) to step the thumbnails up or down. Attachments are fetched only when a template uses them, and the signed-in portal token is applied automatically for secured layers. A left / center / right alignment control positions the strip — handy for centering a lone attachment.
- Spacer — vertical empty space; set its height in pixels with the number stepper.
- Divider — a thin separator rule.
Most blocks (text, date, image, badge, gallery) also expose a left / center / right alignment control.
Add blocks from the button row, reorder them by dragging the grip handle (or
with the up/down controls for keyboard access), and remove them with the trash
button. Every edit compiles the block layout into the same itemTemplate HTML
the runtime renders, so the builder and HTML editor stay in sync.
:::note Migration
Widgets saved before the builder (with mapped titleField / summaryField /
dateField / sourceField) open in the builder with an equivalent default
layout. Their original rendering is preserved until you make the first edit, at
which point the compiled template takes over.
:::
HTML escape hatch
Switch to HTML for full control. The editor is seeded with the compiled builder layout on first switch, then you own the markup. The template is raw HTML/CSS and supports these token types:
The HTML editor is a CodeMirror-based power editor with:
-
Syntax highlighting for HTML/CSS, with template tokens (
{field},{icon:…}, etc.) shown as highlighted pills. -
Autocomplete — type
{to get field names and token prefixes (icon:,image:,date:,attachment:); after a prefix you get context-aware suggestions (icon names, fields, or attachment refs). The closing}is added for you. -
Inline lint — unknown field names, unknown icon names, invalid attachment refs, and unclosed tokens are underlined as warnings. Plain CSS braces (e.g.
.foo{color:red}) are never flagged. -
Format — the Format button re-indents the markup (nested tags two spaces per level) and tidies any embedded
<style>CSS. It only reorganizes whitespace, so tokens and content are never changed. -
Hover — hovering a field-bound token shows the value from the first sample record, so you can preview what will render.
-
{field}— replaced with the value of that attribute on the item. Field names must be plain identifiers (letters, digits, underscore), e.g.{headline}. Values are HTML-escaped. -
{date:Field|pattern}— formats a date field with an optional pattern (see Date format), e.g.{date:created|MMM D, YYYY}. The pattern is optional:{date:created}uses the viewer's localized date/time. -
{icon:name}— replaced with an inline Lucide icon, e.g.{icon:flag}. An explicit kind may be given:{icon:lucide:flag}for a built-in icon, or{icon:resource:icons/ab12.png}for a custom icon uploaded to the workspace (rendered as an<img>resolved against the workspace's portal item). The unqualified{icon:name}form is treated as a Lucide name.{icon:layer-symbol}renders the referenced layer's renderer symbol for the row's feature (the matching unique-value/class-breaks class, or the renderer's single symbol), resolved live from the layer. -
{image:Field}— treats the field's value as an image URL and emits a real<img>, e.g.{image:photoUrl}. The URL is validated (onlyhttp(s)is allowed) and attribute-encoded so query strings survive intact; empty, missing, or unsafe values render nothing. -
{attachment:ref}— renders image attachments from the feature. Usefirst(block image),first:thumb(small square), orall(a wrapping thumbnail strip), e.g.{attachment:all}. Onlyhttp(s)image attachments are emitted; the signed-in portal token is appended for secured layers.
You can include a <style> block with class selectors alongside inline
style="..." attributes:
<style>
.task-card {
padding: 18px 28px;
color: #e5e7eb;
}
.priority-high {
background: #7f1d1d;
color: #fecaca;
}
</style>
<div class="task-card">
<div class="task-title">{name}</div>
<div class="task-priority priority-high">{priority}</div>
<div class="task-description">{description}</div>
</div>
Because {field} tokens are restricted to identifiers, CSS braces (.card { … })
are left untouched. The markup is sanitized before rendering — scripts, event
handlers, and unsafe URLs are stripped.
A <style> block is global: its selectors are not scoped to a single item,
so generic class names can affect other items or the surrounding app. Use
specific class names, or prefer inline style="…" attributes, to avoid leakage.
Live preview
While editing (in either mode) the config panel shows a Live preview that
renders the item against real records sampled from the selected data source. When
the sample contains more than one record, a stepper (‹ 1 / N ›) walks through
them so you can check how the layout handles varied or empty values before
applying it.
Fields & icons palette
In HTML mode, a palette below the editor lists the layer's fields and a
searchable grid of icons. Click a chip to insert its token ({field} or
{icon:name}) at the cursor, or drag a chip and drop it into the editor at a
specific point.
When the sampled records contain fields that hold image URLs, the palette also
shows an Images section with a thumbnail chip per field that inserts an
{image:Field} token.
Date format
Date blocks (and {date:Field|pattern} tokens) format a date field with a
pattern, or fall back to the viewer's localized date/time when no pattern is
set.
Patterns are built from these tokens:
| Token | Renders | Token | Renders | |
|---|---|---|---|---|
YYYY | 4-digit year | dddd | Weekday | |
YY | 2-digit year | ddd | Weekday abbr. | |
MMMM | Month name | HH / H | Hour (24h) | |
MMM | Month abbr. | hh / h | Hour (12h) | |
MM / M | Month number | mm / m | Minute | |
DD / D | Day | ss / s | Second | |
A / a | AM/PM · am/pm |
Wrap literal text in [brackets] to keep letters that would otherwise be read
as tokens, e.g. MMM D [at] h:mm A → Jun 9 at 2:05 PM. Month and weekday
names follow the viewer's locale.
Config panel
- Data — pick the Feature Service and sub-layer (a feature Layer or a Table), with a live preview against sampled records. The selected Feature Service shows a preview card (thumbnail, title, summary, and an open-in-portal link); see Picking an ArcGIS data source. A Filter section under the layer picker limits the list to features matching a SQL expression you build clause by clause (field, operator, and a value or another field), joined with AND/OR. A Sort section orders the results by one or more fields: add a field, toggle it Asc/Desc, drag to set precedence, and remove it. With no sort set, items fall back to the mapped date field (newest first). A Maximum items input caps how many records are shown.
- Appearance — design each item with the Item content editor (the Builder block-based view or the HTML editor, with a live preview against sampled records), then set the per-state item colors under Item states.
Cross-widget actions
The List receives a filter action carrying a MapExtentPayload. Wire a
Map's map:extent-change to narrow items to the current
extent.
The List also emits a list:item-click action. In the config drawer's
Actions section, wire Zoom and/or Pan to a Map or
3D Scene on the same view. Clicking an item then navigates
that map to the item's feature: Zoom frames it (point features use a fixed
padding scale so the map never snaps to its deepest level), while Pan
recenters without changing the zoom. When both are enabled on the same map, zoom
takes precedence. Feature geometry is only fetched once an item-click action is
wired, so unconnected lists pay nothing extra.
Notable behavior
- An item needs at least one block (or a non-empty HTML template) to render.
- Without a Feature Service, the widget shows a configure-me placeholder.
- The optional attribute Filter is combined with the map-extent filter (both must match).
- The extent filter is applied live — items are re-queried when the extent changes.
- Legacy field-mapped widgets keep their original rendering until edited in the builder, then switch to the compiled template.
- All feature fields are available through
{field}(and{date:},{image:}) tokens.