MallaDocs

Bindings and expressions

Bind any text, attribute, style or visibility to an expression that reads live data.

User guide

A binding replaces a fixed value with an expression that reads live data. Text, links, images, attributes, visibility and style values can all be bound. When the data changes, only the bound parts of the page update.

Bind a value

In the inspector, hover a field and press its bind button. Type an expression; autocomplete suggests variables, query fields, item fields and functions from the current scope, and the preview shows the result with live data. Remove the binding to go back to a fixed value.

For a longer expression, press Open in Studio (the expand icon) or ⌘⇧E. The Expression Studio opens under the canvas with the data the expression can read, every function, and the result for each item of a list.

Expressions

Expressions use a safe subset of JavaScript syntax: literals, template strings, arrays and objects with spread, property access with ?., arithmetic, comparisons, &&, ||, ??, the ternary operator, method calls and one-line arrow functions as arguments.

js
// Text
item.title.toUpperCase()
fn.formatCurrency(item.price, 'EUR', 'de-DE')
`${fn.length(queries.cart.data)} items`

// Visibility (hide when this is true)
!user.isLoggedIn

// Style
item.stock > 0 ? 'var(--color-fg)' : 'var(--color-muted)'

// Lists
queries.products.data.filter(p => p.featured).slice(0, 3)
fn.sortBy(queries.posts.data, 'date', 'desc')

What you can read

varsPage and site variables. A page variable shadows a site variable of the same name.
queriesEach query as { data, loading, error, updatedAt }.
item, index, parentInside collection lists and template pages: the current item and its position.
userThe visitor: { isLoggedIn, id, email, name, emailVerified, roles, meta }.
pageThe route: path, params (like :slug) and query string.
siteThe site name and locale.
fnBuilt-in functions and your own formulas: fn.formatDate(…), fn.myFormula(…).
steps, input, event, errorInside workflows: earlier step results, the input, the triggering event and a caught error.

Two-way bindings for inputs

Form controls can be bound both ways with $model: typing updates the variable, and changing the variable updates the input. Use it for search boxes and filters, then read the variable in a query’s input so results refetch as the visitor types.

json
"text":   { "$expr": "item.title" },
"hidden": { "$expr": "!user.isLoggedIn" },
"value":  { "$model": "vars.search" }

Formulas

Formulas are your own reusable functions, defined in the Data workspace with parameters and an expression body, and called as fn.name(…) anywhere. See the expression reference for every built-in.

What ships to visitors

Pages without bindings ship no JavaScript at all. Bound parts become small islands: the HTML is rendered on the server, and a lightweight runtime only updates the bound values in the browser. Bound styles compile to CSS variables set per element.