State & Expressions
Manage state and write expressions
State Types
Constela supports five state types:
number
Numeric values (integers and floating-point).
{
"state": {
"count": { "type": "number", "initial": 0 },
"price": { "type": "number", "initial": 99.99 }
}
}string
Text values.
{
"state": {
"message": { "type": "string", "initial": "" },
"username": { "type": "string", "initial": "Guest" }
}
}list
Arrays of values.
{
"state": {
"items": { "type": "list", "initial": [] },
"todos": {
"type": "list",
"initial": [
{ "id": 1, "text": "Learn Constela", "done": false }
]
}
}
}Note
List items can be any JSON-serializable value: numbers, strings, or objects.
boolean
True/false values for toggles and flags.
{
"state": {
"isOpen": { "type": "boolean", "initial": false },
"darkMode": { "type": "boolean", "initial": true }
}
}Tip
Use boolean state with the toggle operation to easily flip values on user interaction.
object
Structured data with named properties.
{
"state": {
"user": {
"type": "object",
"initial": { "name": "", "email": "" }
},
"form": {
"type": "object",
"initial": { "title": "", "body": "", "tags": [] }
}
}
}Tip
Use object state with the merge operation to update individual properties without replacing the entire object.
Expressions
Expressions are used throughout Constela to compute values dynamically. Every expression has an expr field that specifies its type.
lit - Literal Values
Static values that don't change.
{ "expr": "lit", "value": 42 }
{ "expr": "lit", "value": "Hello, World!" }
{ "expr": "lit", "value": true }
{ "expr": "lit", "value": null }state - State References
Read the current value of a state field.
{ "expr": "state", "name": "count" }
{ "expr": "state", "name": "username" }var - Variable References
Access loop variables or event payloads. Use path to access nested properties.
{ "expr": "var", "name": "item" }
{ "expr": "var", "name": "item", "path": "name" }
{ "expr": "var", "name": "item", "path": "user.email" }
{ "expr": "var", "name": "event", "path": "target.value" }Tip
The var expression is essential for each loops and event handlers. Inside an each block, you can access the current item and its properties.
param - Component Parameters
Access parameters passed to a component.
{ "expr": "param", "name": "title" }
{ "expr": "param", "name": "disabled" }bin - Binary Operations
Perform operations between two expressions.
{
"expr": "bin",
"op": "+",
"left": { "expr": "state", "name": "count" },
"right": { "expr": "lit", "value": 1 }
}not - Logical Negation
Invert a boolean expression.
{
"expr": "not",
"operand": { "expr": "state", "name": "isHidden" }
}cond - Conditional Values
Return different values based on a condition. Unlike the if node that controls what gets rendered, cond computes a value.
{
"expr": "cond",
"if": { "expr": "state", "name": "isDarkMode" },
"then": { "expr": "lit", "value": "#1a1a1a" },
"else": { "expr": "lit", "value": "#ffffff" }
}Use cond for:
- Dynamic text labels
- Conditional CSS classes
- Computed attribute values
get - Property Access
Access nested properties from expressions. Particularly useful with each loops over object arrays.
{
"expr": "get",
"base": { "expr": "var", "name": "item" },
"path": "user.name"
}Tip
While var with path works for simple cases, get makes the property access explicit and works with any base expression.
Binary Operators
The bin expression supports these operators:
Arithmetic Operators
| Operator | Description | Example |
|---|---|---|
+ | Addition | 5 + 3 = 8 |
- | Subtraction | 5 - 3 = 2 |
* | Multiplication | 5 * 3 = 15 |
/ | Division | 6 / 3 = 2 |
{
"expr": "bin",
"op": "*",
"left": { "expr": "state", "name": "quantity" },
"right": { "expr": "state", "name": "price" }
}Comparison Operators
| Operator | Description |
|---|---|
== | Equal |
!= | Not equal |
< | Less than |
<= | Less than or equal |
> | Greater than |
>= | Greater than or equal |
{
"expr": "bin",
"op": ">=",
"left": { "expr": "state", "name": "age" },
"right": { "expr": "lit", "value": 18 }
}Logical Operators
| Operator | Description |
|---|---|
&& | Logical AND |
|| | Logical OR |
{
"expr": "bin",
"op": "&&",
"left": { "expr": "state", "name": "isLoggedIn" },
"right": { "expr": "state", "name": "hasPermission" }
}Expression Examples
Conditional Text
Display different text based on state using the if node:
{
"kind": "if",
"condition": {
"expr": "bin",
"op": ">",
"left": { "expr": "state", "name": "count" },
"right": { "expr": "lit", "value": 0 }
},
"then": {
"kind": "text",
"value": { "expr": "lit", "value": "Count is positive" }
},
"else": {
"kind": "text",
"value": { "expr": "lit", "value": "Count is zero or negative" }
}
}Using cond for Inline Conditional Values
When you need conditional text within an element (not conditional rendering), use the cond expression:
{
"kind": "element",
"tag": "span",
"children": [
{
"kind": "text",
"value": {
"expr": "cond",
"if": {
"expr": "bin",
"op": ">",
"left": { "expr": "state", "name": "count" },
"right": { "expr": "lit", "value": 0 }
},
"then": { "expr": "lit", "value": "Items available" },
"else": { "expr": "lit", "value": "No items" }
}
}
]
}Tip
Use if nodes when you want to conditionally show/hide entire elements. Use cond expressions when you need different values within the same element structure.
Computed Values
Calculate a total from quantity and price:
{
"kind": "text",
"value": {
"expr": "bin",
"op": "*",
"left": { "expr": "state", "name": "quantity" },
"right": { "expr": "state", "name": "price" }
}
}Nested Object Access
Access nested properties from a list item using var with path:
{
"kind": "each",
"items": { "expr": "state", "name": "users" },
"as": "user",
"body": {
"kind": "text",
"value": { "expr": "var", "name": "user", "path": "profile.displayName" }
}
}Object Arrays with get
When iterating over arrays of objects, use get for explicit property access. Combined with cond, you can create rich displays:
{
"kind": "each",
"items": { "expr": "state", "name": "products" },
"as": "product",
"body": {
"kind": "element",
"tag": "div",
"props": { "class": { "expr": "lit", "value": "product-card" } },
"children": [
{
"kind": "element",
"tag": "h3",
"children": [
{
"kind": "text",
"value": {
"expr": "get",
"base": { "expr": "var", "name": "product" },
"path": "name"
}
}
]
},
{
"kind": "text",
"value": {
"expr": "cond",
"if": {
"expr": "get",
"base": { "expr": "var", "name": "product" },
"path": "inStock"
},
"then": { "expr": "lit", "value": "In Stock" },
"else": { "expr": "lit", "value": "Out of Stock" }
}
}
]
}
}Advanced Expressions
For more advanced use cases, Constela provides additional expression types. See the Expressions Reference for complete documentation:
route- Access route parameters, query strings, and current pathindex- Dynamic array/object access with computed keysimport- Access static data from imported JSON filesdata- Access build-time data sources (SSG)ref- Reference DOM elements for JavaScript interop
Next Steps
Learn how to modify state with Actions & Events.