Key Concepts
Event Subscription
A named script attached to a group taxon that runs in response to data changes
Trigger Event
The event type that activates the subscription (
changed:dataAttribute in v1)DependsOn
List of direct child taxon names that trigger the subscription when they change
Script
JavaScript code executed by the GoJA runtime when the event fires
Configuration Reference
A complete event subscription configuration in YAML:Properties
Unique identifier for the subscription within the owning group taxon. Use lowercase with hyphens (e.g.,
lookup-tax-rate).Event type. Must be
"changed:dataAttribute" (the only supported type in the current version).List of direct child taxon names that trigger this subscription. Must reference actual children of the owning group. At least one entry required. No nested paths allowed (e.g.,
"city" not "address/city").JavaScript code executed when the event fires. Runs in the GoJA runtime with a 2-second timeout.
When
true, the subscription is skipped during execution but still validated. Useful for temporarily disabling without removing.Supported Events
| Event Type | Trigger | Description |
|---|---|---|
changed:dataAttribute | User edits an attribute value | Fires when any attribute listed in dependsOn changes on a data object instance of this group |
Additional event types (e.g.,
created:dataObject, deleted:dataAttribute) may be added in future versions. Currently only changed:dataAttribute is supported.Script Globals
When an event subscription script executes, these globals are available:| Global | Type | Description |
|---|---|---|
currentObject | object | The group data object instance where the change occurred |
event | object | Details about the triggering change |
bridge.data.getAttribute(id, tag) | function | Read an attribute value from a data object |
bridge.data.setAttribute(id, tag, value) | function | Write an attribute value on a data object |
serviceBridge.call(ref, endpoint, body) | function | Call an external API via a service bridge |
log(level, message) | function | Write to server logs (debug, info, warn, error) |
console.log(...) | function | Standard console logging |
The event Object
| Property | Type | Description |
|---|---|---|
type | string | Always "changed:dataAttribute" |
attributeTag | string | Name of the changed attribute (e.g., "country") |
attributePath | string | Full path (e.g., "line_items/country") |
dataObjectId | number | ID of the data object that changed |
oldValue | any | Previous value before the change |
newValue | any | New value after the change |
The currentObject API
| Method | Returns | Description |
|---|---|---|
GetID() | number | Data object ID (use with bridge.data.setAttribute) |
GetIDString() | string | Data object ID as string |
GetPath() | string | Taxonomy path of the data object |
GetFirstAttributeValue(name) | any | Current typed value of the named attribute |
GetAttributeValues(name) | string[] | All values of the named attribute as strings |
Reading and Writing Attributes
Reading:Execution Order
When an attribute changes, the platform processes the change in this order:tax_rate will have that value available to any formula referencing tax_rate.
Loop Control
The platform includes three levels of protection against infinite loops:Self-Recursion Guard
Self-Recursion Guard
A subscription cannot trigger itself while it is already running for the same data object. If subscription A writes to an attribute that would trigger subscription A again, the re-trigger is blocked.
Cascade Deduplication
Cascade Deduplication
Within a single user edit cascade, each subscription fires at most once per data object. If subscription A triggers subscription B which tries to re-trigger A, the second A invocation is skipped.
Maximum Depth
Maximum Depth
A hard limit of 8 nested invocations protects against complex mutual recursion. If the cascade depth exceeds 8, execution stops.
Examples
Derive a field from siblings
External lookup on change
Conditional flag setting
Constraints
Each subscription name must be unique within its owning group.
No async/await — all operations are synchronous.
Only
changed:dataAttribute is supported as an event type in the current version.Best Practices
Guard against null
Guard against null
Always start with
if (!currentObject) return; as a guard. This protects against edge cases where the data object context is not available.Single responsibility
Single responsibility
Keep scripts focused on a single responsibility. If you need multiple behaviors, create separate subscriptions with clear names.
Descriptive names
Descriptive names
Use descriptive subscription names that indicate what the script does. Names like
compute-total or lookup-employee-details are clearer than script-1.Test incrementally
Test incrementally
Test with simple values before connecting service bridges. Verify that reads and writes work correctly before adding external API calls.
Use logging during development
Use logging during development
Use
log("debug", ...) during development, then set disabled: true or remove debug logs for production.Disable rather than delete
Disable rather than delete
If a script does not need to run temporarily, use
disabled: true rather than removing it. This preserves the configuration for future use.Related
Formulas Guide
Compute single output values from attribute inputs
Service Bridges
Call external APIs through pre-configured proxies
Data Definitions
Define and configure data structures for extraction
Taxonomy Guide
Comprehensive reference for all taxonomy configuration options
