On this page
No Headings
Last updated: July 24, 2026
Information: This JavaScript SDK documentation uses the CardFields component. If you are integrated with the legacy HostedFields component, see Hosted Field Events.
Subscribe to advanced credit and debit card payment events using an event listener. Event listeners can help you update the UI of your form based on the state of the fields.
You can pass an inputEvents object into a parent cardField component or each card field individually.
Pass an inputEvents object to the parent cardField component to apply the object to every field.
Pass an inputEvents object to an individual card field to apply the object to that field only. This overrides any object passed through a parent component.
You can pass the following callbacks to the inputEvents object:
| Event Name | Description |
|---|---|
onChange | Called when the input in any field changes. |
onFocus | Called when any field gets focus. |
onBlur | Called when any field loses focus. |
onInputSubmitRequest | Called when a payer submits the field. |
Pass the inputEvents object into the parent CardFields component:
const cardField = paypal.CardFields({
inputEvents: {
onChange: function(data) => {
// Do something when an input changes
},
onFocus: function(data) => {
// Do something when a field gets focus
},
onBlur: function(data) => {
// Do something when a field loses focus
}
onInputSubmitRequest: function(data) => {
if (data.isFormValid) {
// Submit the card form for the payer
} else {
// Inform payer that some fields are not valid
}
}
}
})Pass the inputEvents object into each individual field component:
const cardField = paypal.CardFields(/* options */)
const nameField = cardField.NameField({
inputEvents: {
onChange: function(data) => {
// Do something when the input of only the name field changes
},
onFocus: function(data) => {
// Do something when only the name field gets focus
},
onBlur: function(data) => {
// Do something when only name field loses focus
}
onInputSubmitRequest: function(data) => {
if (data.isFormValid) {
// Submit the card form for the payer
} else {
// Inform payer that some fields are not valid
}
}
}
});Each of the event callbacks returns a state object similar to the following example:
data: {
cards: [{code: {name: 'CVV', size: 3}, niceType: "Visa", type: "visa"}]
emittedBy: "number", // Not returned for getState()
isFormValid: false,
errors: ["INVALID_CVV"]
fields: {
cardCvvField: {
isFocused: false,
isEmpty: true,
isValid: false,
isPotentiallyValid: true,
},
cardNumberField: {
isFocused: true,
isEmpty: false,
isValid: false,
isPotentiallyValid: true,
},
cardNameField: {
isFocused: false,
isEmpty: true,
isValid: false,
isPotentiallyValid: true,
},
cardExpiryField: {
isFocused: false,
isEmpty: true,
isValid: false,
isPotentiallyValid: true,
},
},
}Validate individual fields when an input event occurs:
const cardFields = paypal.CardFields({/* options */});
let cardContainer = document.getElementById("#card-number-field-container")
const cardNumberField = cardFields.NumberField({
// Add valid or invalid class when the validation changes on the field
inputEvents: {
onChange: (data) => {
cardContainer.className = data.fields.cardNumberField.isValid ? 'valid' : 'invalid';
}
}
})Validate an entire card form when an input event occurs:
const formContainer = document.getElementById("form-container")
const cardFields = paypal.CardFields({
inputEvents: {
onChange: (data) => {
formContainer.className = data.isFormValid ? 'valid' : 'invalid'
}
}
});The following methods are supported on parent card fields:
getState()isEligible()submit()getState() -> {promise | void}
Returns a promise that resolves into a stateObject. Includes the state of all fields, possible card types, and an array of errors.
Example
const cardField = paypal.CardFields(/* options */)
// ...
// Render the card fields
// ...
cardFields.getState().then((data) => {
// Submit only if the current
// state of the form is valid
if (data.isFormValid) {
cardFields.submit().then(() => {
//Submit success
}).catch((error) => {
//Submit error
});
}
});isEligible() -> {Boolean}
Checks if a cardField instance can render based on configuration and business rules.
Example
const cardField = paypal.CardFields(/* options */)
if (cardFields.isEligible()) {
cardFields.NumberField().render("#card-number-field-container");
cardFields.CVVField().render("#card-cvv-field-container");
// ...
}submit() -> {promise | void}
Submits payment information.
Example
// Add click listener to your submit button
// and call the submit function on the CardField component
multiCardFieldButton.addEventListener("click", () => {
cardField.submit().then(() => {
console.log("Card Fields submit");
}).catch((err) => {
console.log("There was an error with card fields: ", err);
});
});The following methods are supported on individual card fields:
addClass()clear()focus()removeAttribute()removeClass()render()setAttribute()setMessage()close()addClass() -> {promise | void}
Adds a class to a field. Used to update field styles when events occur elsewhere during checkout.
const cardField = paypal.CardFields(/* options */)
const numberField = cardField.NumberField(/* options */)
numberField.addClass("purple");
numberField.render(cardNumberContainer);clear() -> {void}
Clears the value of the field.
const cardField = paypal.CardFields(/* options */)
const nameField = cardField.NameField(/* options */);
nameField.render(cardNameContainer);
nameField.clear();focus() -> {void}
Focuses the field.
const cardField = paypal.CardFields(/* options */)
const nameField = cardField.NameField(/* options */)
nameField.render(cardNameContainer);
nameField.focus();removeAttribute() -> {promise | void}
Removes an attribute from a field where called.
You can remove the following attributes with removeAttribute:
aria-invalidaria-requireddisabledplaceholderconst cardField = paypal.CardFields(/* options */)
const numberField = cardField.NumberField(/* options */)
numberField.render(cardNumberContainer);
numberField.removeAttribute("placeholder");removeClass() -> {promise | void}
Pass the class name as a string in removeClass to remove a class from a field. Used to update field styles when events occur elsewhere in the checkout flow.
const cardField = paypal.CardFields(/* options */)
const numberField = cardField.NumberField(/* options */)
numberField.render(cardNumberContainer);
numberField.removeClass("purple");**render() -> **{promise | void}**** Renders the individual card fields to the DOM for checkout.
Pass the HTML element reference or CSS selector string for the input field.
const cardNumberContainer = document.getElementById("card-number-field-container");
const cardField = paypal.CardFields(/* options */)
cardField.NumberField(/* options */).render(cardNumberContainer);
// OR use a selector string
cardField.NumberField(/*options*/).render("#card-number-field-container")setAttribute() -> {promise | void}
Sets the supported attributes and values of a field. Pass in attributes and values as strings.
const cardField = paypal.CardFields(/* options */)
const nameField = cardField.NameField(/* options */)
nameField.setAttribute("placeholder", "Enter your full name");
nameField.render(cardNameContainer);setMessage() -> {void}
Sets a message on a field for screen readers. Pass the message as a string in setMessage.
const cardField = paypal.CardFields(/* options */)
const nameField = cardField.NameField(/* options */)
nameField.render(cardNameContainer);
nameField.setMessage("Enter your full name");close() -> {promise | void}
Tears down the card field. Use this method to cleanly dispose of the component created by render.
const cardField = paypal.CardFields(/* options */)
const nameField = cardField.NameField(/* options */)
nameField.render(cardNameContainer);
// Call this to tear down nameField
nameField.close();Information about the security code for a card.
| Property | Type | Description |
|---|---|---|
name | string | The name of a security code for a card. Valid values are CVV, CID, and CVC. |
size | number | The expected length of the security code, typically 3 or 4 digits. |
Information about the card type sent in the cards array as a part of the stateObject.
| Property | Type | Description |
|---|---|---|
type | string | The code-readable card type. Valid values are:
|
code | object cardSecurityCode | Contains data about the card brand's security code requirements. For example, on a Visa card, the CVV is 3 digits. On an American Express card, the CID is 4 digits. |
niceType | string | The human-readable card type. Valid values are:
|
Field data for card payments is sent for each card field in the stateObject.
| Property | Type | Description |
|---|---|---|
isFocused | boolean | Shows whether the input field is currently focused. |
isEmpty | boolean | Shows whether the user has entered a value in the input. |
isPotentiallyValid | boolean | Shows whether the current input can be valid. For example, if a payer enters 41 for the card number, the input can become valid. However, if the payer enters 4x, the input can't become valid. |
isValid | boolean | Shows whether the input is valid and can be submitted. |
| Property | Type | Description |
|---|---|---|
cards | array of cardType | Returns an array of potential cards. If the card type has been determined, the array contains only one card. |
emittedBy | string | The name of the field associated with an event. emittedBy is not included if returned by getState. Valid values are "name","number", "cvv", and "expiry". |
errors | array | array of card fields that are currently not valid. Potential values are "INELIGIBLE_CARD_VENDOR","INVALID_NAME", "INVALID_NUMBER", "INVALID_EXPIRY" or "INVALID_CVV". |
isFormValid | boolean | Shows whether the form is valid. |
fields | object | Contains data about the field in the context of the event. Valid values are "cardNameField", "cardCvvField", "cardNumberField" and "cardExpiryField". Each of these keys contain an object of type cardFieldData. |
The following sample shows how a full hosted card fields script might appear in HTML:
<html>
<head>
<meta charset="UTF-8">
<title>Checkout Page</title>
</head>
<body>
<div id="checkout-form">
<div id="card-name-field-container"></div>
<div id="card-number-field-container"></div>
<div id="card-expiry-field-container"></div>
<div id="card-cvv-field-container"></div>
<button id="multi-card-field-button" type="button">Pay now with Card Fields</button>
</div>
</body>
<script src="https://www.paypal.com/sdk/js?client-id=<your-client-id>&components=card-fields"></script>
<script>
// Custom styles object (optional)
const styleObject = {
input: {
"font-size": "16 px",
"font-family": "monospace",
"font-weight": "lighter",
color: "blue",
},
".invalid": {
color: "purple",
},
":hover": {
color: "orange",
},
".purple": {
color: "purple",
},
};
// Create the card fields component and define callbacks
const cardField = paypal.CardFields({
style: styleObject,
createOrder: function (data, actions) {
return fetch("/api/paypal/order/create/", {
method: "post",
})
.then((res) => {
return res.json();
})
.then((orderData) => {
return orderData.id;
});
},
onApprove: function (data, actions) {
const { orderID } = data;
return fetch('/api/paypal/orders/${orderID}/capture/', {
method: "post",
})
.then((res) => {
return res.json();
})
.then((orderData) => {
// Redirect to success page
});
},
inputEvents: {
onChange: function (data) {
// Handle a change event in any of the fields
},
onFocus: function(data) {
// Handle a focus event in any of the fields
},
onBlur: function(data) {
// Handle a blur event in any of the fields
},
onInputSubmitRequest: function(data) {
// Handle an attempt to submit the entire card form
// while focusing any of the fields
}
},
});
// Define the container for each field and the submit button
const cardNameContainer = document.getElementById("card-name-field-container"); // Optional field
const cardNumberContainer = document.getElementById("card-number-field-container");
const cardCvvContainer = document.getElementById("card-cvv-field-container");
const cardExpiryContainer = document.getElementById("card-expiry-field-container");
const multiCardFieldButton = document.getElementById("multi-card-field-button");
// Render each field after checking for eligibility
if (cardField.isEligible()) {
const nameField = cardField.NameField();
nameField.render(cardNameContainer);
const numberField = cardField.NumberField();
numberField.render(cardNumberContainer);
const cvvField = cardField.CVVField();
cvvField.render(cardCvvContainer);
const expiryField = cardField.ExpiryField();
expiryField.render(cardExpiryContainer);
// Add click listener to the submit button and call the submit function on the CardField component
multiCardFieldButton.addEventListener("click", () => {
cardField
.submit()
.then(() => {
// Handle a successful payment
})
.catch((err) => {
// Handle an unsuccessful payment
});
});
}
</script>
</html>Customize Card field properties.
Change the layout, width, height, and outer styling of the card fields.
Customize your integration with script config parameters.