Expressions
Dynamic value interpolation in Orbis
Expressions
Expressions are the core mechanism for making Orbis UIs dynamic. They allow you to compute values, evaluate conditions, and reference data at runtime.
Syntax
Expressions use double curly braces:
{{expression}} They can appear in any string property:
{
"type": "Text",
"content": "Hello, {{state.username}}!"
} Expression Context
Every expression has access to various data sources:
State
Page state values:
"{{state.count}}"
"{{state.user.name}}"
"{{state.items[0]}}" Context
Contextual data (from loops, modals, etc.):
"{{context.modalData}}"
"{{context.parentId}}" Special Variables
Event and iteration context:
| Variable | Description | Available In |
|---|---|---|
$event | Event object | Event handlers |
$event.value | Input value | on_change handlers |
$event.target | Event target | All event handlers |
$item | Current item | Loop, List, Table |
$index | Current index | Loop, List, Table |
$row | Current row | Table components |
$response | API response | call_api on_success |
$response.data | Response body | call_api on_success |
$error | Error object | call_api on_error |
Data Access
Simple Properties
"{{state.username}}" Nested Properties
Use dot notation:
"{{state.user.profile.avatar}}" Array Elements
Use bracket notation:
"{{state.items[0]}}"
"{{state.items[state.selectedIndex]}}" Object Keys
"{{state.users[userId]}}" Operators
Arithmetic
"{{state.count + 1}}"
"{{state.price * state.quantity}}"
"{{state.total - state.discount}}"
"{{state.amount / 100}}"
"{{state.value % 2}}" Comparison
"{{state.count > 0}}"
"{{state.count >= 10}}"
"{{state.age < 18}}"
"{{state.age <= 65}}"
"{{state.status == 'active'}}"
"{{state.status === 'active'}}"
"{{state.type != 'deleted'}}"
"{{state.type !== 'deleted'}}" Logical
"{{state.isActive && state.isVerified}}"
"{{state.isAdmin || state.isModerator}}"
"{{!state.isLoading}}" Ternary
"{{state.count > 0 ? 'Has items' : 'Empty'}}"
"{{state.isActive ? 'active' : 'inactive'}}" String Operations
Concatenation
"{{state.firstName + ' ' + state.lastName}}"
"Hello, {{state.name}}!" Template Strings
Mix static and dynamic content:
"User {{state.username}} has {{state.points}} points" Common Patterns
Conditional Visibility
{
"type": "Alert",
"visible": "{{state.errors.length > 0}}",
"message": "There are errors"
} Dynamic Classes
{
"type": "Container",
"className": "{{state.isActive ? 'bg-primary' : 'bg-muted'}}"
} Computed Labels
{
"type": "Button",
"label": "{{state.isEditing ? 'Save' : 'Edit'}}"
} Disabled States
{
"type": "Button",
"disabled": "{{state.isLoading || !state.isValid}}"
} Loop Item Access
{
"type": "Loop",
"dataSource": "state:items",
"template": {
"type": "Text",
"content": "{{$index + 1}}. {{$item.name}}"
}
} Event Values
{
"type": "Field",
"events": {
"on_change": [
{
"type": "update_state",
"path": "searchQuery",
"value": "$event.value"
}
]
}
} API Response Handling
{
"type": "call_api",
"api": "my-plugin.getData",
"on_success": [
{
"type": "update_state",
"path": "data",
"value": "$response.data"
}
],
"on_error": [
{
"type": "show_toast",
"message": "Error: {{$error.message}}",
"level": "error"
}
]
} Boolean Expressions
Boolean expressions are evaluated for properties like visible, disabled, loading:
{
"visible": true, // Static true
"visible": false, // Static false
"visible": "{{state.show}}", // Dynamic boolean
"visible": "{{state.count > 0 && state.isActive}}" // Complex condition
} Truthy/Falsy Evaluation
Expressions follow JavaScript truthy/falsy rules:
| Value | Boolean Result |
|---|---|
true | true |
false | false |
0 | false |
"" | false |
null | false |
undefined | false |
[] | true (empty array) |
{} | true (empty object) |
| Any non-zero number | true |
| Any non-empty string | true |
Expression Caching
Orbis caches expression results for performance:
- Parsed expressions are memoized
- Unchanged state produces cached results
- Cache is invalidated on state changes
This means repeated re-renders don’t re-parse expressions.
Error Handling
Invalid expressions degrade gracefully:
// Missing property - returns undefined/empty
"{{state.nonexistent}}" // → ""
// Type error - returns empty
"{{state.number.toUpperCase()}}" // → "" (logged in development) In development mode, expression errors are logged to help debugging.
Limitations
No Function Calls
Expressions cannot call arbitrary functions:
// ❌ Not supported
"{{state.items.map(i => i.name)}}"
"{{Date.now()}}"
"{{Math.random()}}" Use computed state or actions instead.
No Assignments
Expressions are read-only:
// ❌ Not supported
"{{state.count = 5}}"
"{{state.count++}}" Use the update_state action to modify state.
No Multi-Statement
Expressions are single expressions:
// ❌ Not supported
"{{let x = 1; x + 2}}" Best Practices
Keep Expressions Simple
// Good
"{{state.isLoggedIn && state.hasPermission}}"
// ❌ Complex - hard to debug
"{{state.users.filter(u => u.active).length > 0 && state.settings.feature}}" Use Descriptive State Names
// Good
"{{state.isSubmitButtonDisabled}}"
// ❌ Unclear
"{{state.d}}" Prefer Pre-Computed State
For complex logic, compute in actions:
// Action that computes value
{
"type": "update_state",
"path": "canSubmit",
"value": "{{state.isValid && !state.isLoading && state.hasChanges}}"
}
// Then use simply
{
"disabled": "{{!state.canSubmit}}"
} Handle Missing Data
// Handle potential undefined
"{{state.user?.name || 'Anonymous'}}"
// Or use conditional rendering
{
"visible": "{{state.user}}",
"content": "{{state.user.name}}"
} Debugging Expressions
Development Mode
Enable debug logging:
RUST_LOG=debug bun run tauri dev Test Expressions
Use the console to test:
{
"type": "Text",
"content": "DEBUG: {{state.myValue}}"
} Check Expression Results
Add debug output:
{
"type": "Conditional",
"condition": "{{state.shouldShow}}",
"then": {
"type": "Text",
"content": "Condition is true"
},
"else": {
"type": "Text",
"content": "Condition is false: {{state.shouldShow}}"
}
} Next Steps
- Event Handling - Responding to user input
- Actions - All action types
- State Management - Managing state
On This Page
- Syntax
- Expression Context
- State
- Context
- Special Variables
- Data Access
- Simple Properties
- Nested Properties
- Array Elements
- Object Keys
- Operators
- Arithmetic
- Comparison
- Logical
- Ternary
- String Operations
- Concatenation
- Template Strings
- Common Patterns
- Conditional Visibility
- Dynamic Classes
- Computed Labels
- Disabled States
- Loop Item Access
- Event Values
- API Response Handling
- Boolean Expressions
- Truthy/Falsy Evaluation
- Expression Caching
- Error Handling
- Limitations
- No Function Calls
- No Assignments
- No Multi-Statement
- Best Practices
- Keep Expressions Simple
- Use Descriptive State Names
- Prefer Pre-Computed State
- Handle Missing Data
- Debugging Expressions
- Development Mode
- Test Expressions
- Check Expression Results
- Next Steps