Expressions

Expressions render dynamic values inside HTML templates using curly braces. They can be used in text and attribute values, in both pages and components.

This is the main way to bind data into markup without leaving the normal Lediv workflow.

Expressions run in a secure subset of JavaScript. Not every JavaScript feature is available by design.

How scope works

Every expression is evaluated against the current scope. Scope is the set of values available at that point in the template.

At page level, scope starts with variables declared in regular <script> blocks and $context. In components, scope includes $context and also $props. Inside loops, each iteration adds its own local variables (for example item and index).

<script>
  const plans = [{ name: 'Starter' }, { name: 'Pro' }];
  const currency = 'EUR';
</script>

<li le-each="{plans as plan, i}">{i + 1}. {plan.name} ({currency})</li>

In this example, currency comes from page/component scope, while plan and i come from the loop scope.

For loop syntax and rendering patterns, see Conditionals and Loops.

What $context and $props mean

$context contains data related to the current page. It is available in the page and in all component instances rendered inside that page. A common example is $context.page.

$props are the input values passed to one component instance. They are available only inside components, and allow the same component to render different content in each usage.

Object Available in Typical use
$context Pages and components Read app-level context values, like current page path.
$props Components only Receive values from component usage attributes.
$editor Pages and components, editor only Editor-only namespace with isActive, variant, and variants properties. See Editable Components.

$context example (page data)

<!-- Page file -->
<script>
  const currentPath = $context.page;
</script>
<small>{currentPath}</small>

$props example (component attributes)

<!-- Page usage -->
<Hero title="Build faster" ctaLabel="{primaryCta}" />

<!-- Hero.html -->
<script>
  const { title, ctaLabel } = $props;
</script>

Use expressions in text and attributes

Wrap any expression with {...}. The same syntax works for text content and for attribute values.

<script>
  const product = 'Starter';
  const price = 19;
  const slug = 'starter';
</script>

<h2>{product} plan</h2>
<p>From {price} €/month</p>
<a href="/pricing/{slug}">View details</a>

Always wrap HTML attribute values in double quotes, including expressions: href="{url}" and not href={url}.

Supported data types

Expressions can read and produce these value types:

Type Examples
String "hello", 'world'
Number 42, 3.14
Boolean true, false
Null values null, undefined
Array [1, 2, 3] (usually consumed with loops or indexing)
Object {label: "Pro", price: 19} (usually consumed via property access)

Scope values should be plain data (primitives, plain objects, and plain arrays). Functions, getters/setters, and symbol keys are blocked.

When the final value is null or undefined, rendered output is an empty string.

Objects are intended for access patterns like plan.name, not direct text rendering of the full object.

Supported operators and syntax

Common expression syntax supported in templates.

Calls are intentionally limited for safety. Top-level function calls like format(price) are not supported.

Allowed methods:

Unsupported syntax

Some JavaScript syntax is intentionally unsupported in templates, including optional chaining, this, new, await, import(), tagged templates, update operators like count++, and sequence expressions.

Where expression values come from

Expressions are evaluated against the current scope. That scope includes variables declared in regular <script> blocks and loop variables, plus $context and (in components) $props.

<script>
  const { title } = $props;
  const pagePath = $context.page;
  const label = title || 'Untitled';
</script>

<h1>{label}</h1>
<p>Current path: {pagePath}</p>

Keep script declarations simple. One variable declaration per statement is the safest pattern for predictable expression scope.

Output behavior

If an expression returns null, undefined, or fails to evaluate, the rendered output is an empty string.

Text expression output is escaped before rendering, so it is treated as text, not as raw HTML.

Show braces literally

When braces should be displayed as plain text (for example in docs snippets), use le-raw on the container element.

<pre le-raw><code>
<p>{title}</p>
</code></pre>

Next steps