App Builder Expressions
Expression syntax reference for dynamic content
Overview
Section titled “Overview”Expressions use {{ }} syntax to inject dynamic values into component properties. They enable:
- Displaying user data
- Accessing workflow results
- Reading form field values
- Conditional logic for visibility/disabled states
- Dynamic navigation paths
Syntax
Section titled “Syntax”Single Expression
Section titled “Single Expression”Returns the raw value (string, number, boolean, object):
{{ user.name }} // "John"{{ variables.count }} // 42{{ user.role == 'admin' }} // true{{ data.items }} // [...]Template Interpolation
Section titled “Template Interpolation”Text with embedded expressions returns a string:
"Hello, {{ user.name }}!" // "Hello, John!""Items: {{ variables.count }}" // "Items: 42""/users/{{ row.id }}/edit" // "/users/abc123/edit"Context Variables
Section titled “Context Variables”Expressions have access to these context variables:
Current authenticated user:
{{ user.id }} // User UUID{{ user.name }} // Display name{{ user.email }} // Email address{{ user.role }} // Role stringvariables
Section titled “variables”Page-level mutable state:
{{ variables.selectedId }}{{ variables.filterText }}{{ variables.currentTab }}Set variables using the set-variable action.
Data from page data sources:
{{ data.customers }} // Array from "customers" data source{{ data.stats.totalRevenue }} // Nested property{{ data.users.0.name }} // Array index accessForm input values (by fieldId):
{{ field.customerName }}{{ field.quantity }}{{ field.isActive }}workflow
Section titled “workflow”Last workflow execution result:
{{ workflow.executionId }} // UUID of execution{{ workflow.status }} // "pending" | "running" | "completed" | "failed"{{ workflow.result }} // Workflow return value{{ workflow.result.orderId }} // Nested result property{{ workflow.error }} // Error message if failedrow (DataTable only)
Section titled “row (DataTable only)”Current row in table actions:
{{ row.id }}{{ row.name }}{{ row.user.email }} // Nested propertyOperators
Section titled “Operators”Comparison
Section titled “Comparison”{{ user.role == 'admin' }} // Equals{{ user.role === 'admin' }} // Strict equals{{ user.role != 'admin' }} // Not equals{{ user.role !== 'admin' }} // Strict not equals{{ variables.count > 10 }} // Greater than{{ variables.count >= 10 }} // Greater than or equal{{ variables.count < 10 }} // Less than{{ variables.count <= 10 }} // Less than or equalLogical
Section titled “Logical”{{ user.isActive && user.isVerified }} // AND{{ user.isAdmin || user.isManager }} // OR{{ !user.isBlocked }} // NOTParentheses
Section titled “Parentheses”{{ (user.role == 'admin' || user.role == 'manager') && user.isActive }}Literals
Section titled “Literals”{{ true }}{{ false }}{{ null }}{{ undefined }}{{ 42 }}{{ 3.14 }}{{ 'single quotes' }}{{ "double quotes" }}Property Access
Section titled “Property Access”Dot Notation
Section titled “Dot Notation”{{ user.profile.name }}{{ data.orders.0.items.0.name }}Nested Objects
Section titled “Nested Objects”Access deeply nested data safely:
{{ data.customer.address.city }} // Returns undefined if any level is missing{{ workflow.result.data.id }}Common Patterns
Section titled “Common Patterns”Conditional Visibility
Section titled “Conditional Visibility”Show component only for admins:
{ "type": "button", "visible": "{{ user.role == 'admin' }}", "props": { "label": "Admin Action" }}Conditional Disable
Section titled “Conditional Disable”Disable button while workflow runs:
{ "type": "button", "props": { "label": "Submit", "disabled": "{{ workflow.status == 'running' }}" }}Disable based on form state:
{ "type": "button", "props": { "label": "Save", "disabled": "{{ !field.name || !field.email }}" }}Dynamic Navigation
Section titled “Dynamic Navigation”Navigate with row data:
{ "onClick": { "type": "navigate", "navigateTo": "/customers/{{ row.id }}" }}Navigate with variables:
{ "onClick": { "type": "navigate", "navigateTo": "/search?q={{ variables.searchTerm }}" }}Workflow Parameters
Section titled “Workflow Parameters”Pass expressions to workflows:
{ "actionType": "workflow", "workflowId": "update_customer", "actionParams": { "id": "{{ variables.customerId }}", "name": "{{ field.customerName }}", "email": "{{ field.customerEmail }}" }}Display Computed Values
Section titled “Display Computed Values”Template interpolation:
{ "type": "text", "props": { "text": "Welcome back, {{ user.name }}! You have {{ data.notifications.length }} new notifications." }}Badge Colors by Status
Section titled “Badge Colors by Status”{ "type": "data-table", "props": { "columns": [ { "key": "status", "header": "Status", "type": "badge", "badgeColors": { "active": "green", "pending": "yellow", "inactive": "gray" } } ] }}Conditional Row Actions
Section titled “Conditional Row Actions”Show action only for certain rows:
{ "rowActions": [ { "label": "Approve", "visible": "{{ row.status == 'pending' }}", "onClick": { "type": "workflow", "workflowId": "approve_item" } } ]}Disable action for locked rows:
{ "rowActions": [ { "label": "Delete", "disabled": "{{ row.isLocked || row.status == 'active' }}", "onClick": { "type": "workflow", "workflowId": "delete_item" } } ]}OnComplete Variable Setting
Section titled “OnComplete Variable Setting”Save workflow result to variable:
{ "onComplete": [ { "type": "set-variable", "variableName": "lastResult", "variableValue": "{{ workflow.result }}" } ]}Evaluation Rules
Section titled “Evaluation Rules”Type Coercion
Section titled “Type Coercion”- Expressions in boolean contexts (
visible,disabled) are coerced to boolean - Empty strings,
null,undefined,0are falsy - Non-empty strings, objects, arrays, non-zero numbers are truthy
Undefined Handling
Section titled “Undefined Handling”- Accessing undefined properties returns
undefined undefinedin templates renders as empty stringundefinedin comparisons should use explicit checks
// Safe pattern for optional values{{ user.middleName || '' }}{{ variables.count || 0 }}Array Access
Section titled “Array Access”{{ data.items.0 }} // First item{{ data.items.0.name }} // First item's name propertyLimitations
Section titled “Limitations”Expressions do not support:
- Function calls (
{{ items.filter(...) }}) - Complex arithmetic beyond comparisons
- Array methods (
map,filter,reduce) - String methods (
toLowerCase(),split()) - Ternary operators (
{{ x ? y : z }}) - use logical OR instead - Object destructuring
For complex transformations, compute values in your workflow and return them in the result.
Debugging
Section titled “Debugging”If expressions don’t evaluate as expected:
- Check property names match exactly (case-sensitive)
- Verify data source is loaded before component renders
- Check for typos in context variable names (
usernotusers) - Use browser dev tools to inspect rendered values