> ## Documentation Index
> Fetch the complete documentation index at: https://learn.nextedy.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Dynamic Value Expressions

> Nextedy POWERSHEET configurations support **dynamic value expressions** — values that are resolved at runtime based on the current context.

export const LastReviewed = ({date}) => {
  if (!date) return null;
  const formatted = new Date(`${date}T00:00:00Z`).toLocaleDateString("en-US", {
    year: "numeric",
    month: "long",
    day: "numeric",
    timeZone: "UTC"
  });
  return <p className="mt-10 text-sm text-gray-400 dark:text-zinc-500 not-prose">
      Last reviewed on {formatted}
    </p>;
};

This concept page explains *why* dynamic expressions exist, *how* the two expression notations differ, and *what mental model you need* to reason about them effectively. For step-by-step configuration instructions, see the relevant [How-To Guides](/powersheet/guides/index).

## Why Dynamic Expressions Matter

Consider a data model where `DesignRequirement` entities link to `SystemRequirement` entities. Without dynamic expressions, a constraint that filters design requirements to a specific component would need to be hardcoded:

```yaml theme={null}
constraints:
  load:
    document:
      component: "Braking"
```

This works for one document but breaks the moment you open a different component's requirements. Dynamic expressions solve this by letting the configuration *ask the runtime* for the correct value:

```yaml theme={null}
constraints:
  load:
    document:
      component: $context.source.document.component
```

Now the same configuration works across every component — Braking, Steering, Powertrain — because the filter value is resolved from the source entity's actual document at the moment the sheet loads.

The same principle applies throughout sheet configuration: filtering queries by the current document, calculating column values from other properties, rendering custom HTML in cells, controlling how navigation properties are displayed, and conditionally styling rows based on data thresholds.

## Two Notations, Two Worlds

Powersheet uses two distinct expression notations. Each belongs to a different configuration file type, and they are **not interchangeable**.

| Notation               | Syntax                   | Configuration File                                               | Evaluation Model               |
| ---------------------- | ------------------------ | ---------------------------------------------------------------- | ------------------------------ |
| **Context expression** | `$context.property.path` | Data model YAML (constraints)                                    | Simple property path traversal |
| **Dynamic value**      | `() => expression`       | Sheet configuration YAML (where, formula, render, display, etc.) | JavaScript arrow function      |

<Frame>
  <img src="https://mintcdn.com/none-17b4493f/3Zik2OH750CE3kB4/powersheet/diagrams/concepts/dynamic-expressions/diagram-1.svg?fit=max&auto=format&n=3Zik2OH750CE3kB4&q=85&s=5a51ba5062f4650c62d3387f401b5f01" alt="diagram" style={{ width: "680px", maxWidth: "100%" }} width="680" height="220" data-path="powersheet/diagrams/concepts/dynamic-expressions/diagram-1.svg" />
</Frame>

<Tip title="Rule of Thumb">
  If you are editing a **data model** YAML file (`domainModelTypes`, `relationships`), use `$context`. If you are editing a **sheet configuration** YAML file (`sources`, `columns`, `formatters`), use `() =>`.
</Tip>

### Context Expressions: Property Path Traversal

Context expressions (`$context.property.path`) are **declarative lookups**. Think of them as a pointer into a data structure — no logic, no computation, just "go to this address and return what you find."

Powersheet resolves a `$context` expression by walking the dot-separated segments at runtime. The expression `$context.source.document.component` means: start at the context object, navigate to `source`, then `document`, then read the `component` property.

This simplicity is intentional. Data model constraints define structural rules about *which* entities can relate to each other. They should be predictable and side-effect-free. A constraint that runs arbitrary JavaScript could introduce subtle bugs across the entire traceability structure.

**Available paths for `$context`:**

| Path                                    | Description                          | Example Value                       |
| --------------------------------------- | ------------------------------------ | ----------------------------------- |
| `$context.source.type`                  | Source entity's work item type       | `"sys_req"`                         |
| `$context.source.document.id`           | Source entity's document ID          | `"Requirements/SRS"`                |
| `$context.source.document.moduleName`   | Source entity's document module name | `"UserNeedSpecification"`           |
| `$context.source.document.moduleFolder` | Source entity's document folder      | `"Requirements"`                    |
| `$context.source.document.component`    | Source entity's document component   | `"Braking"`                         |
| `$context.source.document.type`         | Source entity's document type        | `"systemRequirementsSpecification"` |
| `$context.source.document.title`        | Source entity's document title       | `"System Requirements"`             |

<Note title="Per-Row Evaluation">
  Dynamic constraints with `$context` are evaluated **per-row**. If your sheet displays system requirements from multiple components, each row resolves `$context.source.document.component` independently. Row A might resolve to "Braking" while Row B resolves to "Steering."
</Note>

### Dynamic Values: JavaScript Arrow Functions

Dynamic values (`() => expression`) bring full JavaScript expressiveness to sheet configuration. They can access multiple context properties, perform calculations, construct strings, render HTML, control display values for navigation properties, and apply conditional logic.

The `() =>` syntax is a JavaScript arrow function that receives a `context` object. At runtime, Powersheet evaluates the function and uses the returned value:

```yaml theme={null}
# A formula that multiplies two properties
formula: "() => context.item.quantity * context.item.unitPrice"

# A where clause that scopes results to the current document
where:
  document.moduleName:
    "==": "() => context.document.moduleName"
```

Because these are real JavaScript functions, you have access to standard JavaScript capabilities: string interpolation, array methods, Date objects, arithmetic, and conditional (ternary) operators.

## The Context Object

Both expression notations draw from a shared runtime **context object**. Understanding its structure is the key to writing correct expressions. The context is hierarchical — properties are progressively available depending on where the expression is evaluated.

```
context
|-- parameters          URL and configuration parameters (key-value pairs)
|   +-- {paramName}     e.g. context.parameters.client
|-- user                Current logged-in user
|   +-- id, name
|-- sources             All configured data source definitions
|-- document            Current document information
|   +-- title, type, id, moduleName, moduleFolder, component
|-- tool                Current tool information
|   +-- type
|-- item                Current entity (per-cell contexts only)
|   +-- {propertyName}  e.g. context.item.StoryPoints
|-- source              Parent/source entity (relationship contexts)
|   +-- {propertyName}  e.g. context.source.document.component
|-- entity              Current entity as a plain object
+-- value               Current cell's display value
```

**Not all properties are available everywhere.** The context is scoped based on where the expression runs:

| Usage Location         | `.user` | `.sources` | `.document` | `.item` | `.value` | `.source` | `.entity` |
| ---------------------- | ------- | ---------- | ----------- | ------- | -------- | --------- | --------- |
| `where`                | Yes     | Yes        | Yes         | --      | --       | --        | --        |
| `entityFactory`        | Yes     | Yes        | --          | --      | --       | --        | --        |
| `formula`              | Yes     | Yes        | --          | Yes     | Yes      | Yes       | Yes       |
| `render` / `renderers` | --      | --         | --          | Yes     | Yes      | --        | --        |
| `formatter`            | --      | --         | Yes         | Yes     | Yes      | --        | --        |
| `display`              | --      | --         | --          | Yes     | Yes      | Yes       | --        |

Think of this as a funnel: at the query level (`where`), there is no "current item" yet — the query *finds* items. At the cell level (`formula`, `render`, `display`), each expression runs in the context of a specific item and cell value.

<Warning title="Context Availability Mismatch">
  Referencing `context.item` inside a `where` clause will return `undefined` because the item has not been resolved yet at query time. Similarly, `context.document` is not available in `render` expressions. Always consult the availability table above when writing expressions.
</Warning>

## Where Each Notation Is Used

### Context Expressions in Data Model Constraints

Context expressions appear exclusively in data model constraint definitions — the rules that control which entities can be loaded or picked when navigating relationships.

```yaml theme={null}
relationships:
  - from: DesignRequirement
    to: SystemRequirement
    back:
      name: designRequirements
      constraints:
        load:
          document:
            component: $context.source.document.component
```

This constraint says: when expanding `SystemRequirement` to show linked `DesignRequirement` entities, only load those from documents matching the source's component. The constraint is structural — it shapes what data appears in the sheet.

For more on how constraints work in the data model, see [Process Constraints](/powersheet/concepts/process-constraints) and [Entity Types and Relationships](/powersheet/concepts/entity-types-and-relationships).

### Dynamic Values in Sheet Configuration

Dynamic values appear across several sheet configuration properties, each serving a different purpose:

| Property                  | Purpose                                              | Persists Data? |
| ------------------------- | ---------------------------------------------------- | -------------- |
| `sources.query.where`     | Filter which entities appear in the sheet            | No             |
| `sources.entityFactory`   | Set initial property values for newly created items  | Yes            |
| `columns.*.formula`       | Calculate a column value from other properties       | **Yes**        |
| `columns.*.render`        | Custom HTML rendering for cell display               | No             |
| `columns.*.display`       | Override the display value for navigation properties | No             |
| `renderers.*`             | Named renderer definitions reusable across columns   | No             |
| `formatters.*.expression` | Boolean condition for conditional styling            | No             |

<Warning title="Formula vs Render">
  `formula` and `render` look similar but behave very differently. A `formula` **writes the calculated value back to the data source** — it changes persisted data. A `render` only affects visual display. If you want to show a computed value without modifying underlying data, use `render`. If the computed value should be saved as part of the entity, use `formula`.
</Warning>

### Formatter Expressions: The Exception

Formatter expressions use a simplified syntax that differs from both `$context` and `() =>`:

```yaml theme={null}
formatters:
  criticalHighlight:
    expression: "context.item.Probability <= 99"
    style: warningStyle
```

Notice: no `() =>` prefix, no `$context` prefix. The expression is evaluated directly as a boolean condition. This is a deliberate design choice — formatters only need to answer "does this condition match?" and the simplified syntax makes that intent clear.

## Common Expression Patterns

### Controlling How Navigation Properties Display

The most common use of `() =>` is the `display` property on navigation columns — it controls *which* field of a linked entity appears in the cell. For columns that show a referenced document, `display: titleOrName` is the typical choice; for columns that show a chapter or section reference, use `display: title`:

```yaml theme={null}
columns:
  document:
    binding: source.document
    display: "() => context.value.titleOrName"

  chapter:
    binding: source.chapter
    display: "() => context.value.title"
```

Because `display` runs in a cell context, `context.value` is the linked entity itself, and the arrow function picks the human-readable label without mutating any data. This pattern keeps the underlying binding intact (so navigation, sorting, and saving still work against the real entity) while letting each column choose the most meaningful label.

### Scoping a Query to the Current Document

A common `where` pattern is to restrict a sheet to entities that live in the same document as the powersheet widget. Use `context.document.moduleName` so the query follows whichever document the user has open:

```yaml theme={null}
sources:
  - id: requirements
    query:
      from: SystemRequirement
      where:
        document.moduleName:
          "==": "() => context.document.moduleName"
```

The widget then shows requirements from the current document only — without any per-document configuration.

### Calculating Derived Values

Formulas can reference any property on the current item:

```yaml theme={null}
columns:
  totalPrice:
    formula: "() => context.item.quantity * context.item.unitPrice"
```

### Dynamic Initial Values

When users create new entities from within the sheet, `entityFactory` sets sensible defaults — often by inheriting from the current document:

```yaml theme={null}
entityFactory:
  component: "() => context.document.component"
```

### Custom Cell Rendering

Renderers produce HTML for rich cell content:

```yaml theme={null}
renderers:
  linkedItems: "() => context.value.map((item) => `<b>${item.name}</b>`).join(', ')"
```

### Date Comparisons

JavaScript Date objects work naturally in where clauses:

```yaml theme={null}
where:
  DueDate:
    ">": "() => new Date().toISOString()"
```

<Info title="Verify in application">
  Date values must be in the correct format for the target data type. For Polarion date fields, `.toISOString()` produces the expected format.
</Info>

## Mental Model: Static Structure vs Dynamic Behavior

The two expression types reflect a fundamental architectural division in Powersheet:

* The **data model** defines *what exists* — entity types, relationships, cardinality rules. It is the structural blueprint. Context expressions (`$context`) fit here because they are declarative property lookups that shape data boundaries.

* The **sheet configuration** defines *how things look and behave* — column layout, formatting, calculations, rendering, and the labels shown for navigation properties. Dynamic values (`() =>`) fit here because they need the full expressiveness of runtime computation.

This separation means you can change how data is *displayed* (sheet config) without affecting how data is *structured* (data model), and vice versa. The data model remains a stable foundation that multiple sheet configurations can build upon.

For deeper exploration of this separation, see [Data Model vs Sheet Configuration](/powersheet/concepts/data-model-vs-sheet-config) and [Model-Driven Design](/powersheet/concepts/model-driven-design).

## Quick Reference

| I want to...                            | Notation   | Example                                                            |
| --------------------------------------- | ---------- | ------------------------------------------------------------------ |
| Filter relationships by source document | `$context` | `component: $context.source.document.component`                    |
| Show a document reference in a column   | `() =>`    | `display: "() => context.value.titleOrName"`                       |
| Show a chapter reference in a column    | `() =>`    | `display: "() => context.value.title"`                             |
| Scope query to the current document     | `() =>`    | `"==": "() => context.document.moduleName"`                        |
| Calculate column from other fields      | `() =>`    | `formula: "() => context.item.qty * context.item.price"`           |
| Render custom HTML in a cell            | `() =>`    | `render: "() => '<b>' + context.value + '</b>'"`                   |
| Set default value for new items         | `() =>`    | `entityFactory: { component: "() => context.document.component" }` |
| Conditionally style a cell              | expression | `expression: "context.item.Risk > 50"`                             |

## Further Reading

* [Process Constraints](/powersheet/concepts/process-constraints) — how constraints control entity loading and picking in the data model
* [YAML Configuration System](/powersheet/concepts/yaml-configuration) — the overall configuration architecture that expressions plug into
* [Data Model vs Sheet Configuration](/powersheet/concepts/data-model-vs-sheet-config) — why the two configuration files exist and how they interact
* [Navigation Properties](/powersheet/concepts/navigation-properties) — how expansion paths and the `display` property work together
* [Sheet Configuration Guides](/powersheet/guides/sheet-configuration/index) — practical step-by-step instructions for configuring columns, formatters, and queries
* [Customization Guides](/powersheet/guides/customization/index) — hands-on guides for custom fields and conditional formatting

<LastReviewed date="2026-06-08" />
