Skip to main content

Svelte Components

Use @monei-js/svelte-components to add MONEI payment components to your Svelte 5 app. Each component uses runes-based props and bind:this for submit().

Install​

npm install @monei-js/svelte-components @monei-js/components

Requires Svelte 5 or later. All components use Svelte 5 runes ($props(), $state, $effect) — Svelte 4 is not supported.

Components​

ComponentDescription
CardInputSecure card input (iframe) with submit()
CardNumber / CardExpiry / CardCvcIndividually mountable card fields, coordinated by useCardGroup()
BizumBizum button + phone verification modal
PayPalPayPal checkout button
PaymentRequestApple Pay / Google Pay button

Card input​

The Card Input component collects card number, expiry, and in a single secure iframe. Use bind:this to call submit() and get a .

<script lang="ts">
import {CardInput, confirmPayment} from '@monei-js/svelte-components';

let {paymentId}: {paymentId: string} = $props();
let cardInput: CardInput;
let error = $state('');

function handleChange(event: {error?: string}) {
error = event.error ?? '';
}

async function handleSubmit() {
const result = await cardInput.submit();
if (result.error) {
error = result.error;
return;
}
await confirmPayment({paymentId, paymentToken: result.token});
}
</script>

<div>
<CardInput bind:this="{cardInput}" {paymentId} onChange="{handleChange}" />
<button onclick="{handleSubmit}">Pay</button>
{#if error}
<p>{error}</p>
{/if}
</div>

See the API Reference for all CardInput props (style, placeholders, error messages, event callbacks).

Split card fields​

Mount the number, expiry and CVC as separate components in your own layout. Create the group with useCardGroup() during component init. Pass a thunk for reactive options — changes sync to the group automatically:

<script>
import {CardNumber, CardExpiry, CardCvc, useCardGroup, confirmPayment} from '@monei-js/svelte-components';

let {paymentId} = $props();
const group = useCardGroup(() => ({paymentId}));
let complete = $state(false);
let error = $state('');

async function handleSubmit() {
const result = await group.submit();
if (result.error) {
error = result.error; // the offending field is already highlighted
return;
}
await confirmPayment({paymentId, paymentToken: result.token});
}
</script>

<label>Card number</label>
<CardNumber {group} class="card-box" onChange={(e) => (complete = e.complete)} />
<div class="row">
<div>
<label>Expiry</label>
<CardExpiry {group} class="card-box" />
</div>
<div>
<label>CVC</label>
<CardCvc {group} class="card-box" />
</div>
</div>
<button disabled={!complete} onclick={handleSubmit}>Pay</button>
{#if error}<p>{error}</p>{/if}

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. bind:this on a part exposes focus(), blur() and clear().

See the API Reference for all options and behavior details.

Bizum​

The Bizum component renders a Bizum payment button. When the customer clicks it, a phone verification modal opens to complete the payment.

<script lang="ts">
import {Bizum, confirmPayment} from '@monei-js/svelte-components';

let {paymentId}: {paymentId: string} = $props();

async function handleSubmit(result: {token?: string}) {
if (result.token) {
await confirmPayment({paymentId, paymentToken: result.token});
}
}

function handleError(error: string) {
console.error(error);
}
</script>

<Bizum {paymentId} onSubmit="{handleSubmit}" onError="{handleError}" />

PayPal​

The PayPal component renders a PayPal checkout button. When the customer approves, you receive a token to confirm the payment.

<script lang="ts">
import {PayPal, confirmPayment} from '@monei-js/svelte-components';

let {paymentId}: {paymentId: string} = $props();

async function handleSubmit(result: {token?: string}) {
if (result.token) {
await confirmPayment({paymentId, paymentToken: result.token});
}
}

function handleError(error: string) {
console.error(error);
}
</script>

<PayPal {paymentId} onSubmit="{handleSubmit}" onError="{handleError}" />

PaymentRequest (Apple Pay / Google Pay)​

The PaymentRequest component renders an Apple Pay or Google Pay button depending on the customer's browser and device.

note

Apple Pay requires domain verification in both development and production.

<script lang="ts">
import {PaymentRequest, confirmPayment} from '@monei-js/svelte-components';

let {paymentId}: {paymentId: string} = $props();

async function handleSubmit(result: {token?: string}) {
if (result.token) {
await confirmPayment({paymentId, paymentToken: result.token});
}
}

function handleError(error: string) {
console.error(error);
}
</script>

<PaymentRequest {paymentId} onSubmit="{handleSubmit}" onError="{handleError}" />

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.

<script lang="ts">
import {confirmPayment} from '@monei-js/svelte-components';

let {paymentId}: {paymentId: string} = $props();

async function handleClick() {
const result = await confirmPayment({paymentId});
// Payment completed — check result.status
console.log(result);
}
</script>

<button onclick="{handleClick}">Pay</button>
info

Apple Pay is not available in the Payment Modal. Use the PaymentRequest component instead.

See Use Payment Modal for the full integration guide.

Next steps​

  • Check the API Reference for all component options and methods
  • This is a new package — there was no previous Svelte driver. See the Migration Guide for general v2 → v3 changes