# Events and the store

The widget tells the page what happens through DOM events, and the page's own code can drive the booking through the root's store.

## Events

Every event goes out from the `<mellow-booking>` root, or from a `<mellow-search>` that stands alone. Each one bubbles and is `composed`, so it also leaves a shadow root. Listen on the root, or on `document`:

```js
document.addEventListener("mellow-booked", (event) => {
  const { id, reference } = event.detail;
  window.dataLayer?.push({ event: "booking", reference });
});
```

::::widget-events
- `mellow-ready`: The rental, its locations and its car types are in.
- `mellow-step`: The booking moves to another step. `path` is the address of the new step. Cancelable: a cancelled move does not happen. See [Pages and paths](/widget/pages) for a site with its own router.
- `mellow-search`: The customer sends a search. Cancelable: a cancelled search changes nothing.
- `mellow-choose`: The customer chose a car type.
- `mellow-details`: The customer opened a car type's details. `carTypeId` is the car type's id.
- `mellow-term`: The customer picked a payment term. `refundable` and `confirmationBp` name it, and a new quote follows.
- `mellow-quote`: A new price for the order. The detail is the whole quote of the API, with these fields and more.
- `mellow-before-book`: The customer pressed Pay. The detail is the hold's request. Cancelable: a cancelled Pay holds no car, for the site's own last checks.
- `mellow-booked`: The processor's paid webhook made the booking, or a pay-on-arrival hold booked with no payment. With a test key, `reference` is 0.
- `mellow-paid`: Straight after `mellow-booked`, with the amount paid in minor units and its currency.
- `mellow-error`: The API refused something, such as `none_free`. `message` is in the customer's language.
::::

A cancelable event is cancelled with `event.preventDefault()`.

In Vue, write `@mellow-booked="…"`. In React 19, write `onmellow-booked={…}`: React takes a prop that starts with `on` as a listener on a custom element. The [Next.js recipe](/widget/recipes/nextjs) shows it.

## The store

The root has the store of its booking. A site that needs more than the events reads it and sends actions to it. The store is ready once `storeReady` settles:

```js
const booking = document.querySelector("mellow-booking");
const store = await booking.storeReady;

store.getState(); // the search, the car type, the products, the quote, the step and the rest
const stop = store.subscribe((state) => console.log(state.step)); // gives an unsubscribe
store.setSearch({ pickupAt: "2027-06-01T10:00", returnAt: "2027-06-04T10:00" });
store.choose(carTypeId);
store.setProduct(productId, 1); // 0 takes it off
store.goTo("driver");
```

| Action                           | What it does                                                                                                               |
| -------------------------------- | -------------------------------------------------------------------------------------------------------------------------- |
| `getState()`                     | The state now.                                                                                                             |
| `subscribe(fn)`                  | Calls `fn` with the new state after each change. Gives an unsubscribe.                                                     |
| `setSearch(search)`              | Changes the search: `pickup`, `return`, `pickupAt`, `returnAt`, `driverAge`, `coupon`, `mref`.                             |
| `choose(carTypeId)`              | Chooses a car type.                                                                                                        |
| `setProduct(productId, n)`       | Takes a product `n` times. 0 takes it off. A level or a package with cover takes the place of the one picked.              |
| `decline(productId, on)`         | Refuses a cover that is on every booking, or takes it back. Only a cover that may be refused.                              |
| `setCustomer(customer)`          | Changes the customer's details: `firstName`, `lastName`, `email`, `phone` and the rest.                                    |
| `setCurrency(code)`              | Shows prices in another currency. The charge stays in the rental's.                                                        |
| `missing(step)`                  | What a step still needs, the current step by default. Empty when it is complete.                                           |
| `goTo(step)`, `next()`, `back()` | Moves to a step, the next one or the one before. `goTo` and `next` give false and stay when a step before is not complete. |
| `locate()`                       | Reads the address again, after the site's own router moved.                                                                |
| `pay()`                          | Does what the Pay button does.                                                                                             |

Locations, car types and products go by their id from the API. The [API reference](/api) describes each one.
