Skip to main content

Events

As users interact with Hosted Payment Component fields, custom DOM events are dispatched on each container element. These allow you to react to changes in validation state, focus, and detected card brand without polling or relying solely on CSS class changes.

Available Events

Four custom events are available:

Event NameTriggered WhenDetail Object
hpc.focusThe field gains or loses keyboard focus{ focus: boolean }
hpc.validationThe validation state of the field changes{ validation: { valid, invalid, empty } }
hpc.cardBrandA card brand is detected from the entered number{ cardBrand: string }
hpc.initializationCompleteThe component has finished initializing and is ready for input{} (empty)

Listening for Events

Attach event listeners to your container elements using standard DOM APIs. The events are dispatched on the container element (the div with the configured id), not on elements inside the iframe.

// Get reference to the container element
const cardNumberContainer = document.getElementById('exampleCardNumber');

// Listen for validation changes
cardNumberContainer.addEventListener('hpc.validation', function (e) {
const state = e.detail.validation;
console.log("Valid:", state.valid);
console.log("Invalid:", state.invalid);
console.log("Empty:", state.empty);
});

// Listen for focus changes
cardNumberContainer.addEventListener('hpc.focus', function (e) {
console.log("Field focused:", e.detail.focus);
});

// Listen for card brand detection
cardNumberContainer.addEventListener('hpc.cardBrand', function (e) {
console.log("Detected card brand:", e.detail.cardBrand || "Unknown");
});

Event Details

hpc.validation

Dispatched whenever the validation state of a field changes. This includes when the user starts typing, finishes entering data, or corrects invalid input.

The detail object contains:

PropertyTypeDescription
validation.validBooleantrue if the field content passes all validation rules
validation.invalidBooleantrue if the field content fails validation (e.g., incomplete card number, invalid expiry date)
validation.emptyBooleantrue if the field is empty or has not been interacted with
info

At any given time, exactly one of these three properties will be true. For example, a partially entered but valid-so-far card number may have valid: true, while an incomplete entry that fails Luhn check will have invalid: true.

Example usage — enabling the Pay button only when all fields are valid:

   // Enable Pay button only when all fields are valid
const fields = ['exampleCardNumber', 'exampleExpiryDate', 'exampleCVV'];

function testValidity() {
document.getElementById('examplePay')
.disabled = !fields.every((id) => document.getElementById(id).classList.contains('is-valid'));
}

fields.forEach((id) => document.getElementById(id).addEventListener('hpc.validation', (e) => testValidity()));
testValidity();

hpc.focus

Dispatched when the field gains or loses keyboard focus. Useful for implementing custom focus indicators beyond what feedback classes provide.

The detail object contains:

PropertyTypeDescription
focusBooleantrue if the field has gained focus, false if it has lost focus

Example usage — logging focus transitions for analytics:

document.getElementById('exampleCardNumber').addEventListener('hpc.focus', function (e) {
if (e.detail.focus) {
console.log("User started entering card number");
} else {
console.log("User left card number field");
}
});

hpc.cardBrand

Dispatched when a card brand is detected from the entered card number. This event may fire multiple times as the user types if the brand detection changes (e.g., typing a number that initially matches Visa but later matches Mastercard).

The detail object contains:

PropertyTypeDescription
cardBrandStringThe detected card brand name, or an empty string if no brand could be identified

Currently the following brands are detected and returned:

brand nameDescription
visadVisa Debit
visaeVisa Electron
visaVisa Credit/Debit
visacVisa Credit
mastdMastercard Debit
mastcMastercard Credit
maestrouMaestro UK
maestroiMaestro International
jcbJCB
amexAmex
dinersDiners
discoverDiscover
visatestSandbox test cards (sandbox only)

Example usage — displaying a card brand icon next to the field:

document.getElementById('exampleCardNumber').addEventListener('hpc.cardBrand', function (e) {
const brand = e.detail.cardBrand;
const iconContainer = document.getElementById('card-brand-icon');
if (brand) {
iconContainer.textContent = brand;
iconContainer.style.display = 'block';
} else {
iconContainer.style.display = 'none';
}
});

hpc.initializationComplete

Dispatched when the component has finished loading its iframe and is fully initialized. This event fires once per configured field, asynchronously after the orchestrator constructor returns.

The detail object is empty — the event itself signals readiness.

Example usage — tracking initialization across all fields:

const fields = ['exampleCardNumber', 'exampleExpiryDate', 'exampleCVV'];
let initCount = 0;

fields.forEach(function (id) {
document.getElementById(id).addEventListener('hpc.initializationComplete', function () {
initCount++;
if (initCount === fields.length) {
console.log("All HPC components are ready");
// e.g. show the payment form, enable submit button, etc.
}
});
});
info

The orchestrator constructor returns immediately while iframe loading proceeds asynchronously. Use this event if you need to know when all fields are fully initialized before proceeding (e.g., displaying a hidden payment form).

Events vs Feedback Classes

Both events and feedback classes convey the same underlying state changes. Use feedback classes when you only need visual styling (e.g., changing border colour). Use events when you need to execute logic in response to state changes (e.g., enabling/disabling buttons, updating UI elements, logging analytics).

The two mechanisms are independent — disabling a feedback class by setting it to an empty string does not prevent the corresponding event from firing.

Complete Example

The following demonstrates listening for all four events on each field:

const orchestrator = new OrchestratorMerchant(config);

['exampleCardNumber', 'exampleExpiryDate', 'exampleCVV'].forEach(function (id) {
const container = document.getElementById(id);

// Initialization complete — fires once when the iframe is ready
container.addEventListener('hpc.initializationComplete', function () {
console.log(id, "initialized and ready for input");
});

// Validation state changes
container.addEventListener('hpc.validation', function (e) {
console.log(id, "validation:", e.detail.validation);
});

// Focus state changes
container.addEventListener('hpc.focus', function (e) {
console.log(id, "focused:", e.detail.focus);
});

// Card brand detection (only meaningful for cardNumber field)
if (id === 'exampleCardNumber') {
container.addEventListener('hpc.cardBrand', function (e) {
console.log("Detected brand:", e.detail.cardBrand || "Unknown");
});
}
});