> ## Documentation Index
> Fetch the complete documentation index at: https://discountkit.app/llms.txt
> Use this file to discover all available pages before exploring further.

# Events

> The event <dkl-volume-picker-radio-groups> emits

`<dkl-volume-picker-radio-groups>` is the source of the tier-change event in Discount Kit
Live. It has **no direct reference** to [`<dkl-price>`](/components/price/overview) — instead
it emits a tier-change event that the price (and any of your own code) can listen for,
coupled by event name and product id only.

## Emits

<Note>
  **`widgetId` and `variantId`.** `widgetId` is the **app block's id** — it's `null` on a web component
  which has no block. `variantId` is the product variant the picker is
  bound to.
</Note>

<ParamField body="discount-kit-live:volume-discount:tier-change" type="CustomEvent">
  Fired when a tier is selected or deselected. **Bubbles**, so you can listen on `document`.
  The detail carries `resource`:

  ```ts theme={null}
  {
    productId, variantId, widgetId, widgetType,
    previousTier: VolumeDiscountTier | null,
    currentTier:  VolumeDiscountTier | null,  // null = deselected
    updatesPrice: boolean                     // see below
  }
  // VolumeDiscountTier: { index, quantity, discountAmount, discountType, unitPriceCents }
  ```
</ParamField>

<Note>
  **`updatesPrice`**: Reflects the picker's **"Update price when a tier is selected"** setting
  (`data-update-price-on-change`). When it's `false`, price components like
  [`<dkl-price>`](/components/price/overview) **ignore the tier for pricing** — but the event
  still fires, so your own integrations keep receiving it.

  [`<dkl-price>`](/components/price/overview) listens for this when `updatesPrice` is `true`, matched by product id — a
  selected tier shows the discounted price, a `null` tier reverts to base.
</Note>

A full example payload:

```js theme={null}
// event.detail.resource on tier-change
{
  productId: 7820000000001,
  variantId: 41200000000001,
  widgetId: 'a1b2c3d4',        // the app block's id (null on a web component)
  widgetType: 'volume-picker-radio-groups',
  previousTier: null,
  currentTier: {
    index: 1,
    quantity: 3,
    discountAmount: 10,      // percent for 'percentage', major-unit amount for 'fixedAmount'
    discountType: 'percentage',
    unitPriceCents: 1800     // the per-item discounted price
  },
  updatesPrice: true         // false → <dkl-price> ignores the tier for pricing
}
```

### Lifecycle

Each Volume Picker instance also emits **mount** and **unmount** events as its behaviour
attaches and tears down — handy for wiring up (and cleaning up) custom integrations per
instance. Both **bubble** and carry the same `DklWidgetEventDetail` resource.

<ParamField body="discount-kit-live:widget:mount" type="CustomEvent">
  Fired once the controller has attached its behaviour to the (already server-rendered)
  element. `resource`: `{ widgetType, widgetId, productId?, variantId? }` — `productId` and
  `variantId` are included when known.
</ParamField>

<ParamField body="discount-kit-live:widget:unmount" type="CustomEvent">
  Fired when the instance tears down — e.g. the element is removed, or the theme editor
  re-renders the section. Same `resource` shape. Use it to detach any listeners or observers
  you set up on mount.
</ParamField>

```js theme={null}
// event.detail.resource on widget:mount / widget:unmount
{
  widgetType: 'volume-picker-radio-groups',
  widgetId: 'a1b2c3d4',        // the app block's id (null on a web component)
  productId: 7820000000001,
  variantId: 41200000000001
}
```

## Next steps

<CardGroup cols={2}>
  <Card title="Web Components" icon="code" href="/components/volume-picker/web-component">
    A listener example and how to react to tier changes.
  </Card>

  <Card title="Discount Price" icon="tag" href="/components/price/overview">
    The price display that reacts to this picker's tier-change events.
  </Card>
</CardGroup>
