Skip to content

VueStripeCurrencySelectorElement ​

Lets customers choose the currency they pay in. Use it inside a VueStripeCheckoutElementsProvider (created with checkout.createCurrencySelectorElement(), no beta needed) or inside a VueStripeCheckoutFormProvider (created with the Checkout Form SDK's createCurrencySelectorElement(); the form then leaves out its built-in currency picker). It is created a tick after it mounts, so a VueStripeCheckoutForm rendered after it in the same update exists first: Stripe.js logs an uncaught TypeError when the selector is created before the form. It needs a Checkout Session with Adaptive Pricing enabled, and VueStripeCheckoutElementsProvider must allow it with :adaptive-pricing="{ allowed: true }". Without that prop Stripe.js refuses the element ("You cannot use the Currency Selector Element without allowing Adaptive Pricing"), reported through @loaderror and the #error slot. Stripe.js does not create it in a plain Elements group ("The currencySelector Element cannot be created without using Custom Checkout"), so inside VueStripeElements alone it does not call elements.create(): it reports "VueStripeCurrencySelectorElement is not available inside VueStripeElements" through @loaderror and the #error slot. Inside a VueStripeElements nested in a Checkout provider, it uses the Checkout SDK.

Usage ​

vue
<template>
  <VueStripeProvider :publishable-key="publishableKey">
    <VueStripeCheckoutElementsProvider
      :client-secret="clientSecret"
      :adaptive-pricing="{ allowed: true }"
    >
      <VueStripeCurrencySelectorElement
        @ready="onReady"
        @loaderror="onLoadError"
      />
    </VueStripeCheckoutElementsProvider>
  </VueStripeProvider>
</template>

<script setup lang="ts">
import {
  VueStripeProvider,
  VueStripeCheckoutElementsProvider,
  VueStripeCurrencySelectorElement
} from '@vue-stripe/vue-stripe'
import type { StripeCurrencySelectorElement, StripeError } from '@stripe/stripe-js'
import '@vue-stripe/vue-stripe/style.css' // once, e.g. in main.ts

const publishableKey = import.meta.env.VITE_STRIPE_PUBLISHABLE_KEY
const clientSecret = '<checkout-session-client-secret>'

const onReady = (element: StripeCurrencySelectorElement) =>
  console.log('Currency selector ready', element)
const onLoadError = (event: { error: StripeError }) => console.error('Failed to load', event.error)
</script>

Props ​

PropTypeRequiredDescription
optionsRecord<string, never>NoAccepted like on every element, but this element has no options

The Currency Selector element takes no configuration: Stripe's StripeCurrencySelectorElementOptions is empty and the Checkout SDK's createCurrencySelectorElement() takes no arguments. It derives its choices from the Checkout Session.

Events ​

EventPayloadDescription
@readyStripeCurrencySelectorElementEmitted when the element is fully rendered
@focus{ elementType: 'currencySelector' }Emitted when the element gains focus
@blur{ elementType: 'currencySelector' }Emitted when the element loses focus
@escape{ elementType: 'currencySelector' }Emitted when the user presses the Escape key
@loaderror{ elementType: 'currencySelector'; error: StripeError }Emitted when the element fails to load

@loaderror also fires when creating the element fails (for example inside VueStripeElements without a Checkout provider), with the payload { elementType: 'currencySelector', error: { message } }; the message is also shown through the #error slot.

TIP

The Currency Selector does not emit a @change event — the selected currency is reflected on the reactive session exposed by useCheckoutSession.

Slots ​

SlotSlot PropsDescription
#loading-Rendered while the element is loading (default: "Loading currency selector...")
#error{ error: string }Rendered when the element has an error: a load error or a creation error
vue
<VueStripeCurrencySelectorElement>
  <template #loading>
    <div class="skeleton-loader">Loading...</div>
  </template>

  <template #error="{ error }">
    <p class="my-error">{{ error }}</p>
  </template>
</VueStripeCurrencySelectorElement>

Exposed Methods & Properties ​

Access these via a template ref:

MemberTypeDescription
elementShallowRef<StripeCurrencySelectorElement | null>The Stripe element instance (null until created)
loadingRef<boolean>true until the element emits ready
errorRef<string | null>Current error message (validation, load or creation error)
focus()() => voidFocus the element
blur()() => voidBlur the element
clear()() => voidClear the element's value

The component owns the element's lifecycle: it creates, mounts and destroys the element. Removing the component (for example with v-if) destroys the element, which takes the place of Stripe's element.unmount(); for a one-time listener use Vue's .once modifier (@ready.once) instead of element.once().

Render the sample below inside a VueStripeCheckoutElementsProvider with :adaptive-pricing="{ allowed: true }", as in Usage.

Refs are unwrapped on the template ref, so currencyRef.value.element is a StripeCurrencySelectorElement | null. Type the template ref with the component type and the element with the Stripe type:

vue
<script setup lang="ts">
import { ref } from 'vue'
import { VueStripeCurrencySelectorElement } from '@vue-stripe/vue-stripe'
import type { StripeCurrencySelectorElement } from '@stripe/stripe-js'

const currencyRef = ref<InstanceType<typeof VueStripeCurrencySelectorElement> | null>(null)

const focus = () => currencyRef.value?.focus()
const clear = () => currencyRef.value?.clear()
const stripeElement = (): StripeCurrencySelectorElement | null => currencyRef.value?.element ?? null
</script>

<template>
  <VueStripeCurrencySelectorElement ref="currencyRef" />
  <button type="button" @click="focus">Focus</button>
  <button type="button" @click="clear">Clear</button>
  <p v-if="stripeElement()">The Stripe element exists</p>
</template>

Styling ​

The component renders this markup around Stripe's iframe:

html
<div class="vue-stripe-currency-selector-element vue-stripe-element">
  <!-- only when there is an error; an #error slot replaces the inner div -->
  <div class="vue-stripe-currency-selector-element-error vue-stripe-element-error">
    <div class="vue-stripe-error-message">The error message</div>
  </div>
  <!-- Stripe mounts its iframe here; plus vue-stripe-currency-selector-element-loading / vue-stripe-element-loading while loading -->
  <div class="vue-stripe-currency-selector-element-mount vue-stripe-element-mount"></div>
  <!-- only while loading; a #loading slot replaces the inner div -->
  <div class="vue-stripe-currency-selector-element-loader vue-stripe-element-loader">
    <div class="vue-stripe-loading-message">Loading currency selector...</div>
  </div>
</div>

The default styles for these classes ship in the package stylesheet. Import it once in your app:

ts
import '@vue-stripe/vue-stripe/style.css'

Target .vue-stripe-element* to style every element at once, or .vue-stripe-currency-selector-element* for this one.

TypeScript ​

Render this component inside a VueStripeCheckoutElementsProvider with :adaptive-pricing="{ allowed: true }", as in Usage.

vue
<script setup lang="ts">
import { VueStripeCurrencySelectorElement } from '@vue-stripe/vue-stripe'
import type { StripeCurrencySelectorElement, StripeError } from '@stripe/stripe-js'

const handleReady = (element: StripeCurrencySelectorElement) => {
  console.log('ready', element)
}

const handleLoadError = (event: { elementType: 'currencySelector'; error: StripeError }) => {
  console.error(event.error.message)
}
</script>

<template>
  <VueStripeCurrencySelectorElement
    @ready="handleReady"
    @loaderror="handleLoadError"
  />
</template>

See Also ​