Use your own submit button placed outside the Primer Checkout component to trigger payment.
Recipe
<primer-checkout client-token="your-token">
<primer-main slot="main">
<primer-card-form></primer-card-form>
</primer-main>
</primer-checkout>
<button id="my-pay-button">Pay Now</button>
document.getElementById('my-pay-button').addEventListener('click', () => {
document.dispatchEvent(
new CustomEvent('primer:card-submit', {
bubbles: true,
composed: true,
}),
);
});
How it works
- Place your custom button outside the
<primer-checkout> component
- Listen for click events on your button
- Dispatch the
primer:card-submit custom event to trigger form submission
- The event bubbles up to the card form and initiates the payment
The bubbles: true and composed: true options are required so the event can cross shadow DOM boundaries and reach the card form component.
Variations
With loading state
const payButton = document.getElementById('my-pay-button');
const checkout = document.querySelector('primer-checkout');
payButton.addEventListener('click', () => {
document.dispatchEvent(
new CustomEvent('primer:card-submit', {
bubbles: true,
composed: true,
}),
);
});
// Update button state during processing
checkout.addEventListener('primer:state-change', (event) => {
const { isProcessing } = event.detail;
payButton.disabled = isProcessing;
payButton.textContent = isProcessing ? 'Processing...' : 'Pay Now';
});
Alternatively, you can call the submit method directly on the card form:
const cardForm = document.querySelector('primer-card-form');
const payButton = document.getElementById('my-pay-button');
payButton.addEventListener('click', async () => {
try {
await cardForm.submit();
} catch (error) {
console.error('Submission failed:', error);
}
});
See also