Events
Components communicate through two event buses: a local one per app and a
global one shared across all apps. Both are built on CustomEvent and an
EventTarget.
DOM events: on
Section titled “DOM events: on”For ordinary DOM events inside a component there is on. The listener is removed
automatically on unmount.
on(part("button"), "click", () => open.update((v) => !v));on(window, "resize", onResize, { passive: true });Signature: on(target, event, handler, options?) — options is the native
AddEventListenerOptions.
Local bus (per app)
Section titled “Local bus (per app)”emit / listen on the context talk to the app-internal bus. With it,
components of the same app talk to each other without knowing one another
directly.
// Component Aemit("cart:add", { sku: "abc", qty: 1 });
// Component Blisten("cart:add", (detail) => { console.log("added:", detail);});The same bus is also available directly on the app:
app.emit("cart:add", { sku: "abc" });app.listen("cart:add", (detail) => { /* … */ });Global bus (cross-app)
Section titled “Global bus (cross-app)”The global bus is a singleton shared across all Rivet apps in the document.
Reachable via global on the context or on the app.
// inside a componentglobal.emit("theme:change", { mode: "dark" });global.listen("theme:change", (detail) => applyTheme(detail));
// on the appapp.global.emit("theme:change", { mode: "dark" });Use the global bus for cross-cutting concerns (theme, auth status, locale change). For anything that belongs to one app, the local bus remains the better choice.
Local vs. global
Section titled “Local vs. global”| Bus | Scope | Cleanup in context | Use case |
|---|---|---|---|
| Local | one createRivet() app | automatic | components of one app |
| Global | all apps in the document | automatic | cross-app signals |
Payloads
Section titled “Payloads”The detail is arbitrary (unknown). Cast or validate it in the handler:
type CartAdd = { sku: string; qty: number };
listen("cart:add", (detail) => { const { sku, qty } = detail as CartAdd;});