Events + actions
Events trigger actions. Actions update state or perform effects.
Events connect UI to behavior
Events describe when something happens (click, input, submit, mount). Actions describe what should happen in response (update state, call HTTP, navigate, delay, etc.).
In Thorm, events and actions are both declared inside the IR. That keeps behavior explicit and predictable: it is part of the UI tree, not scattered in hidden callbacks.
Attaching events
Use on(event, action) to attach an action to an event. The event name is a string (e.g., click, input, submit), and the action can be a single action or a composed task.
Because events are props, they live in the same place as attrs() and cls(). This makes it easy to read a node and understand both its structure and its behavior.
Common action helpers
Actions are built with helpers. Some update atoms directly, others trigger side effects.
- set($atom, value) updates state to a new value
- inc($atom, by) increments numeric state
- add($atom, by) adds an expression or value to state
- http(...) performs a request and optionally stores output in atoms
- navigate(...) changes the client-side route
Action helpers can be used directly on events or wrapped inside task() when you need multiple steps.
Composing actions with task
When a single event needs multiple steps, use task([...]) to run actions in order. This keeps complex behavior linear and easy to read.
You can also insert delay(ms, [...]) between steps for user feedback or animations.
If you need the current event payload, use ev(...) to read values from the DOM event. This is common for inputs or custom handlers.
Example: multi-step actions with task()
This example shows how task() chains actions in order. The click handler updates status, logs a message, waits 300ms, increments the counter, then resets the status.
This pattern scales well when a single event needs multiple state changes or side effects. It also keeps behavior readable compared to nested callbacks.
Example: actions that fetch data
This example wires a search input to an HTTP action. Clicking the button triggers http(), which writes to $results and $status. The UI is a direct projection of those atoms.
Notice how actions do not return values to PHP. Instead, they push data into atoms, and the view reads those atoms through expressions. That keeps the flow predictable and reactive.
Practical guidance
- Use task() when you need multiple actions in response to one event.
- Keep event handlers small; move complex workflows into composed actions.
- Treat actions as data. They are part of the IR and should be readable like the rest of the tree.
Events and actions close the loop: they take user input and turn it into state changes or side effects.