Events and methods
Formulas (covered in Reactive Properties and Formulas) are for values that should always reflect their inputs. Events and methods are for the other half of the picture: real, imperative code that runs once, in response to something happening — a click, a collision, a frame tick - and that can call named functions on other objects.
Events vs. methods
An event is triggered by something happening to an object - a click, a hover, a physics collision, a tick of the play clock - and runs a block of code you write for that specific(object, event) pair. A method is a named function you define on an object yourself, callable on demand from an event handler or from another object's code, the same shape as calling a function in any object-oriented language.
Authoring an event or method
Each object exposes its available events and any methods you've defined for it in the properties panel, the same place formulas live. One user-authored handler exists per (object, event) pair - write a new one and it replaces whatever was there, rather than stacking. Worth knowing: some built-in node types install their own internal handlers on top of your own for the same event - a List node'sitem-click dispatch, for instance - and those keep running regardless of what you write; your own handler always runs first, then any of these internal ones run afterward. They don't collide with what you write; they just mean "yours always fires, and so does the node's own built-in behavior."
The built-in event catalog
Three real families of events are available, and which ones show up depends on the object's type and modules:
- Mouse events: click, hover, and related pointer interactions, available on any object.
- The physics collide event: available on objects carrying the Physics module, with a full field set on the event payload: target, targetId, collider, targetCollider, normal, and point - everything you need to know not just that a collision happened, but exactly where and along what surface normal.
- Tick events: fired on the play clock, for continuous per-frame logic that isn't naturally expressed as a bound formula.
Calling a method on another object
From inside a formula, an event handler, or another method, you call a method on a specific object by name and pass it positional arguments matching how that method declares its parameters - the same shape as calling any named function, just routed to a specific object instance. This is what makes methods genuinely useful for cross-object choreography: a collision event on one object can call a method defined on a completely different object, triggering that object's own logic rather than duplicating it inline.
Creating and removing objects at runtime, from code
Beyond reading and calling things that already exist, event and method code has access to a real, DOM-like object-creation API: creating a new element by type, or a new instance of an existing component definition, and explicitly adding or removing it from the document. Neither creation call attaches the new object to the document automatically - you get a detached object back and have to explicitly add it yourself, the same two-step "create, then attach" pattern DOM APIs use. This is a genuinely powerful, imperative capability that a bound formula can't do (formulas describe a value, they don't have side effects)— spawning a burst of particles, instantiating a new copy of a component when something happens, or cleaning up an object that's served its purpose, are all things that belong in a method or an event handler, not a formula.
Worked examples
Click-to-trigger: a Button object's click event calls ctx.callMethod ('player1', 'jump') - clicking the button runs the jump method you defined on a completely different object.
Collision-to-spawn: a collide event reads the event's point field (where the collision happened) and creates a new particle-burst component instance positioned at that exact point, then attaches it to the document — a one-off spawn, not a permanently bound relationship the way a formula would create.
Next up — Custom property slots: giving an object or a component a parameter that isn't one of Formo's built-in properties.