# Vue Components

Use `@monei-js/vue-components` to add MONEI payment components to your Vue 3 app. Each component is a native Vue component with typed props and template ref `submit()`.

<!-- -->

## Install[​](#install "Direct link to Install")

* npm
* yarn
* pnpm

```
npm install @monei-js/vue-components @monei-js/components
```

```
yarn add @monei-js/vue-components @monei-js/components
```

```
pnpm add @monei-js/vue-components @monei-js/components
```

Requires Vue 3.3 or later.

## Components[​](#components "Direct link to Components")

| Component                               | Description                                                         |
| --------------------------------------- | ------------------------------------------------------------------- |
| `CardInput`                             | Secure card input (iframe) with `submit()`                          |
| `CardNumber` / `CardExpiry` / `CardCvc` | Individually mountable card fields, coordinated by `useCardGroup()` |
| `Bizum`                                 | Bizum button + phone verification modal                             |
| `PayPal`                                | PayPal checkout button                                              |
| `PaymentRequest`                        | Apple Pay / Google Pay button                                       |

## Card input[​](#card-input "Direct link to Card input")

The Card Input component collects card number, expiry, and CVC in a single secure iframe. Use a template ref to call `submit()` and get a payment token.

```
<template>

  <div>

    <CardInput ref="cardInput" :payment-id="paymentId" :on-change="handleChange" />

    <button @click="handleSubmit">Pay</button>

    <p v-if="error">{{ error }}</p>

  </div>

</template>



<script setup lang="ts">

  import {ref} from 'vue';

  import {CardInput, confirmPayment} from '@monei-js/vue-components';



  const props = defineProps<{paymentId: string}>();

  const cardInput = ref<InstanceType<typeof CardInput>>();

  const error = ref('');



  function handleChange(event: {error?: string}) {

    error.value = event.error ?? '';

  }



  async function handleSubmit() {

    const result = await cardInput.value!.submit();

    if (result.error) {

      error.value = result.error;

      return;

    }

    await confirmPayment({paymentId: props.paymentId, paymentToken: result.token});

  }

</script>
```

Open in CodeSandbox

See the [API Reference](https://docs.monei.com/monei-js/reference/.md#cardinput-component) for all CardInput props (style, placeholders, error messages, event callbacks).

## Split card fields[​](#split-card-fields "Direct link to Split card fields")

Mount the number, expiry and CVC as separate components in your own layout. Create the group with `useCardGroup()` inside `setup()` — payment identifiers live on the group, the parts take presentation props only.

```
<script setup>

import {ref} from 'vue';

import {

  CardNumber,

  CardExpiry,

  CardCvc,

  useCardGroup,

  confirmPayment

} from '@monei-js/vue-components';



const props = defineProps({paymentId: String});

const group = useCardGroup({paymentId: props.paymentId});

const complete = ref(false);

const error = ref('');



async function handleSubmit() {

  const result = await group.submit();

  if (result.error) {

    error.value = result.error; // the offending field is already highlighted

    return;

  }

  await confirmPayment({paymentId: props.paymentId, paymentToken: result.token});

}

</script>



<template>

  <label>Card number</label>

  <CardNumber :group="group" class="card-box" :onChange="(e) => (complete = e.complete)" />

  <div class="row">

    <div>

      <label>Expiry</label>

      <CardExpiry :group="group" class="card-box" />

    </div>

    <div>

      <label>CVC</label>

      <CardCvc :group="group" class="card-box" />

    </div>

  </div>

  <button :disabled="!complete" @click="handleSubmit">Pay</button>

  <p v-if="error">{{ error }}</p>

</template>
```

Open in CodeSandbox

Style that box in your own CSS — the `class` you pass is set on the very element each part toggles `monei-component--focus`, `--invalid`, `--empty` and `--complete` on, so `.card-box.monei-component--invalid {}` matches. A template ref on a part exposes `focus()`, `blur()` and `clear()`.

See the [API Reference](https://docs.monei.com/monei-js/reference/.md#card-part-components) for all options and behavior details.

## Bizum[​](#bizum "Direct link to Bizum")

The [Bizum](https://docs.monei.com/payment-methods/bizum/.md) component renders a Bizum payment button. When the customer clicks it, a phone verification modal opens to complete the payment.

```
<template>

  <Bizum :payment-id="paymentId" :on-submit="handleSubmit" :on-error="handleError" />

</template>



<script setup lang="ts">

  import {Bizum, confirmPayment} from '@monei-js/vue-components';



  const props = defineProps<{paymentId: string}>();



  async function handleSubmit(result: {token?: string}) {

    if (result.token) {

      await confirmPayment({paymentId: props.paymentId, paymentToken: result.token});

    }

  }



  function handleError(error: string) {

    console.error(error);

  }

</script>
```

Open in CodeSandbox

## PayPal[​](#paypal "Direct link to PayPal")

The [PayPal](https://docs.monei.com/payment-methods/paypal/.md) component renders a PayPal checkout button. When the customer approves, you receive a token to confirm the payment.

```
<template>

  <PayPal :payment-id="paymentId" :on-submit="handleSubmit" :on-error="handleError" />

</template>



<script setup lang="ts">

  import {PayPal, confirmPayment} from '@monei-js/vue-components';



  const props = defineProps<{paymentId: string}>();



  async function handleSubmit(result: {token?: string}) {

    if (result.token) {

      await confirmPayment({paymentId: props.paymentId, paymentToken: result.token});

    }

  }



  function handleError(error: string) {

    console.error(error);

  }

</script>
```

Open in CodeSandbox

## PaymentRequest (Apple Pay / Google Pay)[​](#paymentrequest-apple-pay--google-pay "Direct link to PaymentRequest (Apple Pay / Google Pay)")

The [PaymentRequest](https://docs.monei.com/payment-methods/apple-pay/.md) component renders an Apple Pay or Google Pay button depending on the customer's browser and device.

note

Apple Pay requires [domain verification](https://docs.monei.com/payment-methods/apple-pay/.md#register-your-domain-with-apple-pay) in both development and production.

```
<template>

  <PaymentRequest :payment-id="paymentId" :on-submit="handleSubmit" :on-error="handleError" />

</template>



<script setup lang="ts">

  import {PaymentRequest, confirmPayment} from '@monei-js/vue-components';



  const props = defineProps<{paymentId: string}>();



  async function handleSubmit(result: {token?: string}) {

    if (result.token) {

      await confirmPayment({paymentId: props.paymentId, paymentToken: result.token});

    }

  }



  function handleError(error: string) {

    console.error(error);

  }

</script>
```

Open in CodeSandbox

## Payment modal[​](#payment-modal "Direct link to Payment modal")

Calling `confirmPayment()` **without** a `paymentToken` opens the MONEI Payment Modal — a full in-page checkout where the customer can select a payment method and complete the payment.

```
<template>

  <button @click="handleClick">Pay</button>

</template>



<script setup lang="ts">

  import {confirmPayment} from '@monei-js/vue-components';



  const props = defineProps<{paymentId: string}>();



  async function handleClick() {

    const result = await confirmPayment({paymentId: props.paymentId});

    // Payment completed — check result.status

    console.log(result);

  }

</script>
```

info

Apple Pay is not available in the Payment Modal. Use the [PaymentRequest](#paymentrequest-apple-pay--google-pay) component instead.

See [Use Payment Modal](https://docs.monei.com/integrations/use-payment-modal/.md) for the full integration guide.

## Next steps[​](#next-steps "Direct link to Next steps")

* Check the [API Reference](https://docs.monei.com/monei-js/reference/.md) for all component options and methods
* See the [Migration Guide](https://docs.monei.com/monei-js/migration/.md) if you're upgrading from the `.driver('vue3')` API
