Canvas Items And CanvasBuilder

What It Is

This chapter explains the practical authoring model behind Jetstack canvases:

  • how CanvasBuilder works
  • what a canvas item is
  • how item settings are stored
  • how nested items, active areas, scopes, and runtime values work
  • which item families are available and when to use them

Use this chapter after reading:

Why It Matters

Most of the real power of canvases does not live in the top-level canvas form. It lives in the item tree edited in CanvasBuilder.

If you understand CanvasBuilder well, you can:

  • assemble full pages
  • embed views, forms, and nested canvases
  • work with object context
  • prepare variables for later items
  • build reusable fragments
  • create property-oriented templates

Mental Model

A canvas is a tree of items.

Each item has:

  • a stable generated item ID
  • a title used in the builder
  • a class defining what the item does
  • input parameters whose values are expressions evaluated at render time
  • optional child zones called active areas
  • optional hidden state
  • optional elevated-permissions state

At runtime, the canvas renderer walks the tree and asks each item to produce HTML. Each item's expressions are evaluated against the canvas's code processor, with the surrounding tree context (object wrapper, iterator, current user, …) bound in as variables.

The result is not a flat HTML template authored by hand. It is a structured composition graph stored as serialized item objects.

A Note On Legacy Canvases

Some canvases authored before the current expression model may still hold their input parameter values in the legacy chain-builder format. They keep working without changes. When you open the settings modal of such an item, the builder shows a one-click migration assistant that translates the stored chains into the current expression form, flags any parts that need a manual rewrite, and lets you confirm the conversion before committing it. After migration the item behaves like any newly created one.

How CanvasBuilder Works

CanvasBuilder is the dedicated authoring interface for the item tree.

Its main working areas are:

  • the item gallery on the left
  • the editable canvas area on the right
  • the draft indicator and publish controls
  • the meta dialog
  • the item settings modal
  • the parameter-arguments modal

Draft Workflow

CanvasBuilder loads the draft if one exists. Otherwise it loads the published content.

This means:

  • edits normally go into content_draft
  • the live canvas keeps using content until you publish

The builder exposes:

  • Publish
  • Discard draft

Use this workflow when:

  • the canvas is already live
  • you want to iterate safely

Core Builder Operations

Add Item

How it works:

  • drag or drop from the item gallery into the main canvas or into an item's active area

What it means:

  • the builder creates a new item instance of the chosen class
  • if added into a child zone, the item becomes part of that parent item's active area

Move Item

How it works:

  • drag an existing item to a new position or zone

What it means:

  • the builder reorders the serialized tree or moves the item to a different active area

Copy Item

How it works:

  • use the item's copy action

What it means:

  • the item is cloned
  • the copy receives a new item ID
  • child items also receive regenerated IDs

Use it when:

  • a block should be duplicated and then adjusted

Delete Item

How it works:

  • use the delete action on the item

What it means:

  • the item is removed from the canvas tree
  • child items inside it are removed with it

Rename Item

How it works:

  • change the item title in the builder

What it means:

  • the title improves builder readability
  • it usually does not change runtime behavior directly

Use titles generously for:

  • repeated similar items
  • layout sections
  • nested forms
  • reusable snippets

Set a Public ID

How it works:

  • click the link-icon button next to Change title in the item's edit controls
  • enter a free-form identifier (e.g. my-card, profile-row)
  • the current value is shown as a small badge; click the badge to copy it

What it means:

  • the rendered wrapper element gets data-soopio-id="<your-id>"
  • Run JavaScript automation code can target it via Jetstack.getElement('<your-id>') or Jetstack.getElements('<your-id>')
  • the Public ID survives duplication and is independent of the internal item ID and any HTML id input parameter
  • when the item is rendered inside an iterator, each row gets <your-id>#<iteratorUniqueId> — use Jetstack.getElements to match every row

Use Public IDs for any canvas item you plan to reference from a RunJavaScriptAction.

Hide Item

How it works:

  • toggle the hidden flag in the builder

What it means:

  • hidden items do not render in runtime mode
  • they can still remain in the builder tree for later use or temporary suppression

Use it when:

  • testing alternatives
  • parking a block temporarily
  • disabling one section without deleting its configuration

Elevated Permissions

How it works:

  • toggle the item's elevated-permissions flag

What it means:

  • the item can request a more privileged execution mode in the places that honor this flag
  • this is especially relevant for some form and operation items

Use it carefully:

  • elevated permissions are a governance decision, not only a convenience setting

Item Anatomy

Every item class defines its own configuration through input parameter definitions.

Those definitions can specify:

  • parameter name
  • expected type
  • default value
  • UI control type
  • conditional visibility
  • redraw-on-change behavior
  • value picker type
  • context for resource pickers
  • whether the value should be sandboxed before rendering

Shared Item Parameters

Most items inherit several common parameters.

class

What it controls:

  • HTML class added to the wrapper output

Use it when:

  • a block needs styling hooks
  • a custom wrapper class improves CSS targeting

id

What it controls:

  • HTML ID added to the rendered wrapper

Use it when:

  • a block needs a DOM anchor or JS hook

reloadDuringAjax

What it controls:

  • whether the item should be redrawn during AJAX updates

Use it when:

  • the item output depends on state that changes during AJAX operations

isReloadableContent

What it controls:

  • whether the item should expose itself as reloadable content

Use it when:

  • the item is a content region that should be refreshable after interactions

iterate

What it controls:

  • whether the item should repeat over an iterable source

Why it matters:

  • this is one of the key ways canvases become data-driven
  • iterated items gain iterator context for nested content

Active Areas

An active area is a named child zone inside an item.

Examples:

  • a Row has an inner area for columns
  • an If item has if_true and if_false
  • a Card has areas for body-like child content
  • a CustomForm has an inner area for fields

Why it matters:

  • active areas are what make nesting possible
  • they let layout and structural items act as containers rather than only leaf nodes

Use them to:

  • create layout structure
  • separate conditional branches
  • embed fields inside forms
  • build nested fragment hierarchies

Values In Item Settings

Each input parameter on a canvas item holds an expression. The expression is evaluated by the canvas's code processor when the item is about to render, against the surrounding tree context.

In practice, an expression can be:

  • a literal: 42, 'hello', true, false, null
  • a reference to an in-scope variable: currentUser, iteratorItem.email, parentObject.id
  • a function call: today(), concat('Hello, ', currentUser.first_name), appParameter('id')
  • a chained property access through relations: iteratorItem.created_by.email
  • arithmetic, boolean, and ternary expressions: iteratorItem.price * 1.21, currentUser.email ?? 'guest'
  • rich-text content with embedded shortcodes (in editor-mode fields, see below)

The settings modal renders one editor per parameter. Most parameters use a code editor with autocomplete; the rest use specialized controls (selects, checkboxes, type pickers, rich-text editors) when the parameter type calls for one.

Resource Pickers

Some parameters declare a valueType, which means the builder treats them as references to platform resources and renders a dedicated picker instead of a free-form expression editor.

Common picker types include:

  • automation
  • canvas
  • email template
  • module
  • property
  • query
  • role
  • type
  • view

Some also declare a valueTypeContext, which means the valid options depend on another parameter. For example, a property picker uses typeId as its context so the builder offers the properties of the chosen type.

Rich-Text Editor Mode

A few content items (notably P) offer a switch between an Editor mode (TinyMCE rich-text) and an Expression mode (code editor). Use Editor mode when the value is mostly static markup with a few dynamic insertions; use Expression mode when the value is a single computed expression.

In Editor mode, dynamic insertions use the shortcode forms documented under Shortcodes In Rich-Text Fields.

Conditional Parameters

Item parameters can appear or disappear depending on other parameter values.

Examples:

  • the canvas item's advanced selector is shown only when the main canvas selector is set to _advanced_
  • the embedded view item shows different fields depending on whether it is using a defined view, a query, parameter-built query, or custom SQL

Why it matters:

  • the settings UI is adaptive
  • think of an item as a small stateful configuration object, not a flat form

Redraw-On-Change Parameters

Some parameters cause the settings table to redraw when they change. Selecting one mode (e.g. switching inputType between Editor and Expression on a P item) can reveal entirely different follow-up fields, and changing a base parameter can change the available downstream choices.

Available Context

When you author an expression for an item, the canvas exposes a set of in-scope variables and helper functions. What is in scope depends on where the item sits in the tree.

Always Available

These variables and helpers exist in every item, regardless of position:

TokenMeaning
currentUserThe currently authenticated user resource
true, false, nullLiteral values
var('name')A canvas-level variable set by Set variable items or by preload automation
templateVar('name')A variable from the surrounding page template
env('name')A tenant-wide environment variable from app settings
appParameter('name')A request/route parameter
selection()The selection app parameter (id + selection list combined)
formStatus('formId')Submission status of a form by its form id
queryResultCount(queryId)Number of rows for a stored Query
queryResultCalc(queryId, 'propId', 'code')Calculation result for a stored Query
today(), date(...), formatDate(...)Date helpers
concat(...), map(...), length(...)String and collection helpers
+, -, *, /, ==, !=, &&, `

The full helper catalog is shared with automations: see Code Processor Functions.

Tree-Position-Derived

Two variables depend on what kind of ancestor wraps the item:

TokenWhen it resolves
iteratorItemThe current item of the nearest iterator-role ancestor (GeneralIterator, QueryIterator, TableGeneralIterator, or any item with iterate set)
iteratorIndexThe zero-based index in that iteration
parentObjectThe pinned object of the nearest non-iterator Object wrapper ancestor — iterators are transparently skipped, so parentObject always refers to the surrounding "real" object context

The truth table for typical nestings:

Ancestor chain (innermost → outermost)iteratorItemparentObject
(none)
Object wrapper(Order)Order
GeneralIterator(Product)current Product
Object wrapper(Order)GeneralIterator(LineItem)current LineItemOrder
Object wrapper(Order)Object wrapper(Customer)Customer (innermost wrapper wins)
Object wrapper(Order)GeneralIteratorGeneralIteratorinnermost iterator's itemOrder

The rule: iteratorItem follows the nearest iterator-role ancestor; parentObject follows the nearest non-iterator object wrapper.

Type-Aware Autocomplete

When you place the cursor in an expression editor, the canvas builder offers two complementary aids.

Variables Panel

A collapsible panel above the parameter table shows every variable currently in scope, grouped by source (Built-in, Functions, Iterator, Parent object, Canvas variables). Click a chip to insert it at the caret of the most recently focused expression editor.

When iteratorItem or parentObject resolves to a known typed object (the surrounding ancestor declares a fixed typeId), the panel expands to list that type's fields directly, e.g. iteratorItem.email, iteratorItem.created_on, parentObject.title.

Inline Hints

Inside the editor, two hint sources are blended:

  • typing a known root and a dot — iteratorItem., parentObject., currentUser. — opens an inline list of that type's fields. Continuing through a relation extends the chain: iteratorItem.created_by. follows the user relation and offers User's fields.
  • typing any identifier — con, cur, for, … — offers the matching builder-in functions and root variables.

Ctrl+Space triggers the same hint provider manually. Hints are resolved live: when you cross from a known type into a relation that hasn't been seen before, the builder asks the server for that type's schema and serves the hints on the next keystroke.

When the surrounding ancestor's typeId is itself dynamic (set by another expression), the hint system falls back to the bare root — you can still type the chain, you just don't get autocomplete past the root.

See also:

Applying Changes

The settings modal accumulates expression edits locally. Nothing is persisted to the canvas draft until you click Apply changes, at which point the entire set of changed expressions for that item is committed in one round trip and the canvas redraws. Closing the modal without applying discards the pending edits.

This is intentional: it lets you experiment freely inside the modal without polluting the draft until you are satisfied with the whole configuration.

Pickers (selects, checkboxes, resource pickers) commit immediately on change because they often need to drive redrawOnChange behavior in the same modal.

Shortcodes In Rich-Text Fields

Rich-text Editor-mode fields support two embedded shortcode forms inside the HTML content. They are evaluated against the same code processor and tree context as expression-mode fields.

FormResolved byUse it for
{=expression}The canvas code processorInline computed values, function calls, conditionals: {=currentUser.first_name}, {=concat('#', parentObject.id)}
{$variable.path}Variable resolution against the canvas contextPlain context lookups in legacy or simpler form: {$currentUser.email}

Errors during shortcode evaluation are swallowed — a malformed {=...} fragment renders as the original placeholder rather than breaking the page.

See:

Item Families

The item gallery is grouped by capability. The exact classes come from the canvas item registry, but in practice the gallery is organized around these families.

Layout Items

These items define structure and placement.

Common layout items:

  • If
  • Block
  • Row
  • Col
  • Spacer
  • Card
  • Tabs

Use them when:

  • you need layout hierarchy
  • content should be conditionally shown
  • sections should be visually grouped
  • the canvas needs a clear page structure

Special note on If:

  • it has if_true and if_false child areas
  • it is a structural branching tool inside the canvas itself

Content Items

These items render content-oriented structures.

Common content items:

  • Table
  • Table custom
  • Tr
  • Td
  • TableGeneralIterator
  • TableQueryIterator
  • H1 to H6
  • P
  • Span
  • Image
  • Link

Use them when:

  • the canvas needs textual or media content
  • you want manual tabular structure
  • repeated content should be rendered row by row

Object Items

These items work with object context and object rendering.

Common object items:

  • Object wrapper
  • Object render
  • Property value
  • Object overview
  • Object comments
  • GeneralIterator
  • QueryIterator

Why they matter:

  • they are the main bridge between the canvas and Jetstack's data model

Object wrapper

Use it when:

  • a subtree should work against one current object context
  • child items need parentObject access

Object render

Use it when:

  • you want the platform to render a whole object surface inside the canvas

Property value

Use it when:

  • a canvas should display one specific field from an object

Iterators

Use them when:

  • one block should repeat over a general iterable or query result
  • child items should gain iterator context

Widget Items

These items are general-purpose compositional helpers and integrations.

Common widget items:

  • Set variable
  • Set variable by Automation
  • Set variable by Callback
  • View
  • Canvas
  • Custom HTML
  • Replicator item template

Variable Items

Use them when:

  • later items need a prepared canvas variable
  • a preload automation would be too broad for one local value

Embedded View

Use it when:

  • a canvas should embed a normal Jetstack view

Its main modes are:

  • defined view
  • dynamic view with defined query
  • dynamic view from query parameters
  • dynamic view from custom SQL

This makes it one of the most important bridge items between canvases and views.

Embedded Canvas

Use it when:

  • one canvas should render another canvas

This is the main composition mechanism behind snippet-like reuse.

Custom HTML

Use it when:

  • the layout needs custom markup that is still anchored inside the canvas item model

Important behavior:

  • it supports a gallery of nested child elements exposed through shortcodes
  • it also supports injected variables

Use it carefully:

  • prefer structured items where possible
  • reach for custom HTML when the structured item palette is not expressive enough

Replicator item template

Use it when:

  • building property-oriented repeated-entry layouts, especially for replicators

Form Items

These items build custom forms and form fields inside canvases.

Common form items:

  • Custom form
  • Form
  • CustomFormField
  • FormField
  • FormLabel
  • FormControl

Why they matter:

  • forms are one of the strongest reasons to use canvases
  • they let you build custom entry and editing flows with automation hooks

Custom form

Use it when:

  • the canvas should host a fully custom form layout and field set

Form

Use it when:

  • the canvas should host a structured object form tied to a type and form mode

Form Event Automations

Form items can wire automations to events such as:

  • anchor
  • reload
  • validate
  • submit
  • success
  • after success
  • error

This makes forms inside canvases highly composable with the automation system.

Choosing The Right Item Family

Use this rule of thumb:

  • choose Layout items to shape space
  • choose Content items to render text, media, or manual structure
  • choose Object items to bind the canvas to domain data
  • choose Widget items to compose behavior and embed other platform surfaces
  • choose Form items when the canvas becomes an input flow

Common CanvasBuilder Patterns

Page Canvas With Object Context

Typical structure:

  • Object wrapper
  • layout items for sections
  • property-value or object-overview items
  • embedded view blocks for related records

Use it for:

  • detail pages
  • rich object dashboards

Reusable Snippet Canvas

Typical structure:

  • a small layout skeleton
  • a few object-aware or variable-aware items
  • optional custom HTML for tight presentation

Use it for:

  • shared summary blocks
  • headers
  • reusable side sections

Widget Canvas

Typical structure:

  • small layout
  • one or two variable-setting items
  • one embedded view or KPI-oriented fragment

Use it for:

  • dashboards
  • role-specific summary panels

Custom Form Flow

Typical structure:

  • Custom form or Form
  • field items
  • automation hooks on anchor, validate, submit, and success

Use it for:

  • guided entry flows
  • custom object editing experiences
  • property-level repeated-entry templates

Practical Guidance For Safe Builder Work

  • Use titles on items so the tree stays understandable.
  • Keep one clear responsibility per item whenever possible.
  • Prefer structured items before custom HTML or callback code.
  • Use snippet canvases to avoid duplicating large blocks.
  • Keep variable-setting items close to the sections that use them.
  • Use iterators deliberately and make sure nested content clearly depends on them.
  • Treat elevated permissions as an exception, not a default.
  • Publish intentionally and use drafts for experimentation.

Design Questions To Ask While Building

  • Does this canvas really need a custom block here, or would a standard embedded view be better?
  • Should this value be a literal, derived from parentObject / iteratorItem, or a computed expression?
  • Does this subtree need object context (an Object wrapper) or iterator context (a GeneralIterator / QueryIterator)?
  • Would a reusable snippet be better than repeating the same block in several canvases?
  • Is custom HTML solving a real limitation, or hiding an avoidable design problem?