# salla-multiple-bundle-product-options-modal (https://docs.salla.dev/twilight/react/web-components/salla-multiple-bundle-product-options-modal)



{/* Generated by scripts/sync-web-components.mjs from the components docs.json. Do not edit by hand. */}

<Callout title="Used inside salla-multiple-bundle-product">
  [`<salla-multiple-bundle-product>`](https://docs.salla.dev/twilight/react/web-components/salla-multiple-bundle-product) renders this component for you. You rarely use it directly.
</Callout>

Modal where a customer picks the options (size, color and so on) of one product inside a multiple bundle.
Used inside `salla-multiple-bundle-product-details`, which renders it once; a theme rarely places it directly.

It has no props. The parent opens it by dispatching `multiple-bundle-product-modal::open` on `salla.event` with
`{ product, sectionId, sectionIndex, productIndex, isProductAlreadySelected }`, and clears the saved options of a
product with `multiple-bundle-product-modal::clear-options` and `{ productId, sectionId, sectionIndex, productIndex }`.
On save it validates the selection (at least one option, and every `required` option), writes hidden
`bundle[sectionId][productIndex][options][optionId]` inputs into the closest `<form>`, dispatches a `change`
event on that form, emits `optionsSaved` and `productSelected`, and closes. The Save button is disabled while
loading or when a selected option value is out of stock (`is_out`).

## Use it [#use-it]

In HTML or JSX, use the tag `<salla-multiple-bundle-product-options-modal>` with the **Attribute** names below. In React, the wrapper takes the **Property** names (camelCase).

```tsx
import { SallaMultipleBundleProductOptionsModal } from '@salla.sa/twilight-components-react/multiple-bundle-product-options-modal';
```

**Client-only.** On the server this wrapper renders a placeholder (a skeleton, or nothing), and the real component mounts in the browser. Do not rely on it for content that search engines must see.

## Example [#example]

```ts
salla.event.dispatch('multiple-bundle-product-modal::open', {
  product: bundleProduct, // { id, name, images, options: [...] }
  sectionId: 12,
  sectionIndex: 0,
  productIndex: 0,
});
```

## Events [#events]

Listen with `addEventListener`, or the `on` prop of the React wrapper (for example `onModalBack`).

| Event             | Description                                                                                                                                                                                                   | Detail                                                                                                           |
| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- |
| `optionsSaved`    | Emitted after the options are saved to the form. `event.detail` is `{ productId, selectedOptions, sectionId, productIndex }`, where `selectedOptions` is the list of chosen option values.                    | `{ productId: number; selectedOptions: SelectedOption[]; sectionId?: string \| number; productIndex?: number; }` |
| `productSelected` | Emitted after a successful save when a section id is known, so the parent can mark the product as selected. `event.detail` is `{ productId, sectionId, product, fromModal }`, with `fromModal` always `true`. | `{ productId: number; sectionId: string \| number; product?: BundleProduct; fromModal?: boolean; }`              |

## Methods [#methods]

Call these on the element or a React ref.

### `close() => Promise<void>` [#close--promisevoid]

Closes the modal. Resolves with no value.

### `open() => Promise<void>` [#open--promisevoid]

Opens the modal for the current product (set through the `multiple-bundle-product-modal::open` event),
shows a loading state, and restores the options already chosen for it. Resolves with no value.

### `refreshOptionsState() => Promise<void>` [#refreshoptionsstate--promisevoid]

Forces a re-render of the options from the internally tracked selections. Resolves with no value.

## Related [#related]

Renders: [`<salla-modal>`](https://docs.salla.dev/twilight/react/web-components/salla-modal), [`<salla-skeleton>`](https://docs.salla.dev/twilight/react/web-components/salla-skeleton), [`<salla-slider>`](https://docs.salla.dev/twilight/react/web-components/salla-slider), [`<salla-product-options>`](https://docs.salla.dev/twilight/react/web-components/salla-product-options), [`<salla-button>`](https://docs.salla.dev/twilight/react/web-components/salla-button).

Used inside: [`<salla-multiple-bundle-product-details>`](https://docs.salla.dev/twilight/react/web-components/salla-multiple-bundle-product-details).
