Handle events and callbacks
The embed reports what happens inside it through a small, typed event contract. Use it to route navigation, sync URL state, and react to reservations, payments, and errors.
Every event is delivered two ways:
- A
mount()callback, for exampleonNavigate. Use callbacks for normal integrations. - A DOM
CustomEventnamedcoras:<name>, dispatched from the mounted container. UseaddEventListeneronly for advanced cases, such as delegating to existing listeners.
Both carry the same detail payload.
Events at a glance
Section titled “Events at a glance”| Event | Callback | When it fires |
|---|---|---|
coras:ready |
onReady |
The page mounted and the first render is ready. |
coras:navigate |
onNavigate |
The embed requests navigation. The host should route. |
coras:state-change |
onStateChange |
In-page state changed, such as filters or selection. |
coras:reservation-created |
onReservationCreated |
A reservation was created. |
coras:payment-status |
onPaymentStatus |
Payment status changed. |
coras:error |
onError |
A safe, redacted error occurred. |
Handle events with callbacks
Section titled “Handle events with callbacks”Pass callbacks to mount(). Each receives the event detail directly.
import { mount } from "@coras-io/embed";
const app = mount({ container, page: "landing", config, onReady({ page }) { // page: "landing" | "search" | "details" | "payment" | "help" | "suggestion-widget" }, onNavigate(intent) { // intent: { page, params?, locale?, currency?, href?, source } router.navigate(intent); }, onStateChange(state) { // state: { page, params, locale?, currency? } }, onReservationCreated({ reservationId, expiresIn, ticketDeliveryMethod }) { // all three fields are optional }, onPaymentStatus({ status, reference }) { // status: "succeeded" | "failed" | "pending" // reference is an optional public reference, never a provider secret }, onError({ code, message, page }) { // code: stable machine code, e.g. "invalid_page_params" },});Route navigation, not state changes
Section titled “Route navigation, not state changes”coras:navigate and coras:state-change look similar but have different jobs.
Keep them separate to avoid router loops.
coras:navigateis a request to navigate: a cross-page action such as opening details or running a search, or an external link. The host maps the intent to its router and callsapp.update().coras:state-changereports in-page state such as filters or selection. The host decides whether to persist this state in the URL.
For the full pattern, see Routing.
Handle events with addEventListener
Section titled “Handle events with addEventListener”Listen on the same container you passed to mount(). The detail payload
matches the callback argument.
container.addEventListener("coras:navigate", (event) => { console.log(event.detail.page, event.detail.source);});When a page has multiple mounts, each event and callback reaches only its own instance.
Observe lifecycle events
Section titled “Observe lifecycle events”onObservability reports per-mount lifecycle and diagnostic facts, separate from
the coras:* host events. Names are dot-namespaced, for example
coras.page-loaded, coras.unmounted, and coras.error.
mount({ container, page: "landing", config, onObservability(event) { // event: { name, page?, data? } },});The events emitted today, with the keys they carry in data:
| Name | When it fires | data keys |
|---|---|---|
coras.page-loaded |
A page finished its first render. | { page } |
coras.error |
A redacted error was reported. | { code } |
coras.unmounted |
The mount was torn down. | None. |
Treat name and data as an open set: more events and keys can be added.
data values are limited to strings, numbers, booleans, and null.