Custom JavaScript Overview
Custom JavaScript is the escape hatch for behavior the no-code builder cannot express — computed fields, custom sorting, dynamic chart transformations, and cross-widget coordination. It runs in a sandboxed environment with controlled APIs and no network access.
What Custom JS Enables
Custom JS scripts are attached to individual widgets. They run when the widget renders or when specific widget events fire, giving you access to the widget's data and the ability to modify app variables and trigger actions:
- Compute derived values from widget data and set them as app variables
- Transform chart data (reformat, sort, aggregate) before the chart renders
- Implement custom table sorting or filtering logic
- Trigger navigation or modal actions based on complex computed conditions
- Read widget data and run custom validation beyond what form rules support
When to Use Custom JS
| Use Custom JS for | Use token expressions instead for |
|---|---|
| Multi-step data transformation (sorting, grouping, mapping arrays) | Simple value display: {{ row.name }} |
| Computed values requiring imperative logic (loops, reduce) | Conditional display: {{ status === 'active' ? 'Yes' : 'No' }} |
| Reacting to widget lifecycle events (onLoad, onDataChange) | Role-based visibility: {{ context.roles.includes('admin') }} |
| Dynamic chart series generation | Filtering a data source with params |
Security Model Summary
Custom JS runs in a sandboxed JavaScript execution environment. The sandbox provides controlled APIs and blocks everything else:
// AVAILABLE in Custom JS:
widget.data // The widget's current loaded data
widget.props // The widget's resolved configuration
variables.get(name) // Read an app variable
variables.set(name, value) // Write an app variable (triggers re-render)
actions.navigate(path) // Trigger navigation
actions.openModal(modalId) // Open a modal
actions.triggerWorkflow(id, inputs) // Fire a workflow
context.userId // Current user's ID
context.roles // Current user's roles
// BLOCKED in Custom JS:
fetch() // No network calls
XMLHttpRequest // No network calls
localStorage // No browser storage access
document // No DOM manipulation
window // No global scope access
setTimeout (>100ms) // Async abuse blocked
In This Guide
Custom JS Editor
The in-builder code editor with syntax highlighting and auto-complete.
Available APIs
Full reference for widget.data, variables, actions, and context APIs.
Reading Widget Data
Access the widget's current data and resolved token values.
Setting Variables
Use variables.set() to drive reactive updates from custom JS.
Triggering Actions
Navigate, open modals, trigger workflows from custom JS.
Execution Sandbox
What is blocked and why — network, DOM, global scope.
Examples
Custom sorting, calculated fields, dynamic chart configuration.