Skip to main content
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.

Why Dynamic Expressions Matter

Consider a domain 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:
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:
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 URL parameters, calculating column values from other properties, rendering custom HTML in cells, 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.
NotationSyntaxConfiguration FileEvaluation Model
Context expression$context.property.pathDomain model YAML (constraints)Simple property path traversal
Dynamic value() => expressionSheet configuration YAML (where, formula, render, etc.)JavaScript arrow function
diagram
If you are editing a domain model YAML file (domainModelTypes, relationships), use $context. If you are editing a sheet configuration YAML file (sources, columns, formatters), use () =>.

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. Domain 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:
PathDescriptionExample Value
$context.source.typeSource entity’s work item type"sys_req"
$context.source.document.idSource entity’s document ID"Requirements/SRS"
$context.source.document.moduleNameSource entity’s document module name"UserNeedSpecification"
$context.source.document.moduleFolderSource entity’s document folder"Requirements"
$context.source.document.componentSource entity’s document component"Braking"
$context.source.document.typeSource entity’s document type"systemRequirementsSpecification"
$context.source.document.titleSource entity’s document title"System Requirements"
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.”

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, 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:
# A formula that multiplies two properties
formula: "() => context.item.quantity * context.item.unitPrice"

# A where clause that reads a URL parameter
where:
  Client:
    "==": "() => context.parameters.client"
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
whereYesYesYes
entityFactoryYesYes
formulaYesYesYesYesYesYes
render / renderersYesYes
formatterYesYesYes
displayYesYesYes
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), each expression runs in the context of a specific item and cell value.
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.

Where Each Notation Is Used

Context Expressions in Domain Model Constraints

Context expressions appear exclusively in domain model constraint definitions — the rules that control which entities can be loaded or picked when navigating relationships.
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 domain model, see Process Constraints and Entity Types and Relationships.

Dynamic Values in Sheet Configuration

Dynamic values appear across several sheet configuration properties, each serving a different purpose:
PropertyPurposePersists Data?
sources.query.whereFilter which entities appear in the sheetNo
sources.entityFactorySet initial property values for newly created itemsYes
columns.*.formulaCalculate a column value from other propertiesYes
columns.*.renderCustom HTML rendering for cell displayNo
columns.*.displayOverride the display value for navigation propertiesNo
renderers.*Named renderer definitions reusable across columnsNo
formatters.*.expressionBoolean condition for conditional stylingNo
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.

Formatter Expressions: The Exception

Formatter expressions use a simplified syntax that differs from both $context and () =>:
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

Filtering by URL Parameters

URL parameters let external links or widgets pass filter values into the sheet:
sources:
  - id: opportunities
    query:
      from: Opportunity
      where:
        Client:
          "==": "() => context.parameters.client"
A URL like ?client=Acme would filter the sheet to show only Acme’s opportunities.

Calculating Derived Values

Formulas can reference any property on the current item:
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:
entityFactory:
  Client: "() => context.parameters.client"

Custom Cell Rendering

Renderers produce HTML for rich cell content:
renderers:
  linkedItems: "() => context.value.map((item) => `<b>${item.name}</b>`).join(', ')"

Date Comparisons

JavaScript Date objects work naturally in where clauses:
where:
  DueDate:
    ">": "() => new Date().toISOString()"
Date values must be in the correct format for the target data type. For Polarion date fields, .toISOString() produces the expected format.

Mental Model: Static Structure vs Dynamic Behavior

The two expression types reflect a fundamental architectural division in Powersheet:
  • The domain 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. 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 (domain model), and vice versa. The domain model remains a stable foundation that multiple sheet configurations can build upon. For deeper exploration of this separation, see Data Model vs Sheet Configuration and Model-Driven Design.

Quick Reference

I want to…NotationExample
Filter relationships by source document$contextcomponent: $context.source.document.component
Filter query by URL parameter() =>"==": "() => context.parameters.client"
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: { Client: "() => context.parameters.client" }
Conditionally style a cellexpressionexpression: "context.item.Risk > 50"

Further Reading