Subscribe to Card Field events
DocsCurrentAdvancedLast updated: April 24th 2024, @ 3:47:01 pm
Important: This JavaScript SDK documentation uses the
CardFields
component. If you are integrated with the legacyHostedFields
component, see Hosted Field Events.
Subscribe to 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.
inputEvents
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.
Supported input event callbacks
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. |
Example: inputEvents into parent component
Pass the inputEvents
object into the parent CardFields
component:
1const cardField = paypal.CardFields({2 inputEvents: {3 onChange: function(data) => {4 // Do something when an input changes5 },6 onFocus: function(data) => {7 // Do something when a field gets focus8 },9 onBlur: function(data) => {10 // Do something when a field loses focus11 }12 onInputSubmitRequest: function(data) => {13 if (data.isFormValid) {14 // Submit the card form for the payer15 } else {16 // Inform payer that some fields are not valid17 }18 }19 }20 })
Example: inputEvents into individual component
Pass the inputEvents
object into each individual field component:
1const cardField = paypal.CardFields(/* options */)2const nameField = cardField.NameField({3 inputEvents: {4 onChange: function(data) => {5 // Do something when the input of only the name field changes6 },7 onFocus: function(data) => {8 // Do something when only the name field gets focus9 },10 onBlur: function(data) => {11 // Do something when only name field loses focus12 }13 onInputSubmitRequest: function(data) => {14 if (data.isFormValid) {15 // Submit the card form for the payer16 } else {17 // Inform payer that some fields are not valid18 }19 }20 }21 });
Sample state object
Each of the event callbacks returns a state object similar to the following example:
1data: {2 cards: [{code: {name: 'CVV', size: 3}, niceType: "Visa", type: "visa"}]3 emittedBy: "number", // Not returned for getState()4 isFormValid: false,5 errors: ["INVALID_CVV"]6 fields: {7 cardCvvField: {8 isFocused: false,9 isEmpty: true,10 isValid: false,11 isPotentiallyValid: true,12 },13 cardNumberField: {14 isFocused: true,15 isEmpty: false,16 isValid: false,17 isPotentiallyValid: true,18 },19 cardNameField: {20 isFocused: false,21 isEmpty: true,22 isValid: false,23 isPotentiallyValid: true,24 },25 cardExpiryField: {26 isFocused: false,27 isEmpty: true,28 isValid: false,29 isPotentiallyValid: true,30 },31 },32 }
Validate individual fields
Validate individual fields when an input event occurs:
1const cardFields = paypal.CardFields({/* options */});2let cardContainer = document.getElementById("#card-number-field-container")3const cardNumberField = cardFields.NumberField({4 // Add valid or invalid class when the validation changes on the field5 inputEvents: {6 onChange: (data) => {7 cardContainer.className = data.fields.cardNumberField.isValid ? 'valid' : 'invalid';8 }9 }10 })
Validate entire card form
Validate an entire card form when an input event occurs:
1const formContainer = document.getElementById("form-container")2const cardFields = paypal.CardFields({3 inputEvents: {4 onChange: (data) => {5 formContainer.className = data.isFormValid ? 'valid' : 'invalid'6 }7 }8 });
Methods on parent card fields
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
1const cardField = paypal.CardFields(/* options */)2 // ...3 // Render the card fields4 // ...5 cardFields.getState().then((data) => {6 // Submit only if the current7 // state of the form is valid8 if (data.isFormValid) {9 cardFields.submit().then(() => {10 //Submit success11 }).catch((error) => {12 //Submit error13 });14 }15 });
isEligible() -> {Boolean}
Checks if a cardField
instance can render based on configuration and business rules.
Example
1const cardField = paypal.CardFields(/* options */)2if (cardFields.isEligible()) {3 cardFields.NumberField().render("#card-number-field-container");4 cardFields.CVVField().render("#card-cvv-field-container");5 // ...6}
submit() -> {promise | void}
Submits payment information.
1// Add click listener to your submit button2// and call the submit function on the CardField component3multiCardFieldButton.addEventListener("click", () => {4 cardField.submit().then(() => {5 console.log("Card Fields submit");6 }).catch((err) => {7 console.log("There was an error with card fields: ", err);8 });9});
Methods on individual card fields
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.
1const cardField = paypal.CardFields(/* options */)2const numberField = cardField.NumberField(/* options */)3numberField.addClass("purple");4numberField.render(cardNumberContainer);
clear() -> {void}
Clears the value of the field.
1const cardField = paypal.CardFields(/* options */)2const nameField = cardField.NameField(/* options */);3nameField.render(cardNameContainer);4nameField.clear();
focus() -> {void}
Focuses the field.
1const cardField = paypal.CardFields(/* options */)2const nameField = cardField.NameField(/* options */)3nameField.render(cardNameContainer);4nameField.focus();
removeAttribute() -> {promise | void}
Removes an attribute from a field where called.
Supported attributes to remove
You can remove the following attributes with removeAttribute
:
aria-invalid
aria-required
disabled
placeholder
1const cardField = paypal.CardFields(/* options */)2const numberField = cardField.NumberField(/* options */)3numberField.render(cardNumberContainer);4numberField.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.
1const cardField = paypal.CardFields(/* options */)2const numberField = cardField.NumberField(/* options */)3numberField.render(cardNumberContainer);4numberField.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.
1const cardNumberContainer = document.getElementById("card-number-field-container");2const cardField = paypal.CardFields(/* options */)3cardField.NumberField(/* options */).render(cardNumberContainer);4// OR use a selector string5cardField.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.
1const cardField = paypal.CardFields(/* options */)2const nameField = cardField.NameField(/* options */)3nameField.setAttribute("placeholder", "Enter your full name");4nameField.render(cardNameContainer);
setMessage() -> {void}
Sets a message on a field for screen readers. Pass the message as a string in setMessage
.
1const cardField = paypal.CardFields(/* options */)2const nameField = cardField.NameField(/* options */)3nameField.render(cardNameContainer);4nameField.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
.
1const cardField = paypal.CardFields(/* options */)2const nameField = cardField.NameField(/* options */)3nameField.render(cardNameContainer);4// Call this to tear down nameField5nameField.close();
Type definitions
cardSecurityCode
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. |
cardType
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:
|
cardFieldData
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. |
stateObject
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. |
Full example
The following sample shows how a full hosted card fields script might appear in HTML:
1<html>2 <head>3 <meta charset="UTF-8">4 <title>Checkout Page</title>5 </head>6 <body>7 <div id="checkout-form">8 <div id="card-name-field-container"></div>9 <div id="card-number-field-container"></div>10 <div id="card-expiry-field-container"></div>11 <div id="card-cvv-field-container"></div>12 <button id="multi-card-field-button" type="button">Pay now with Card Fields</button>13 </div>14 </body>15 <script src="https://www.paypal.com/sdk/js?client-id=<your-client-id>&components=card-fields"></script>16 <script>17 // Custom styles object (optional)18 const styleObject = {19 input: {20 "font-size": "16 px",21 "font-family": "monospace",22 "font-weight": "lighter",23 color: "blue",24 },25 ".invalid": {26 color: "purple",27 },28 ":hover": {29 color: "orange",30 },31 ".purple": {32 color: "purple",33 },34 };35 // Create the card fields component and define callbacks36 const cardField = paypal.CardFields({37 style: styleObject,38 createOrder: function (data, actions) {39 return fetch("/api/paypal/order/create/", {40 method: "post",41 })42 .then((res) => {43 return res.json();44 })45 .then((orderData) => {46 return orderData.id;47 });48 },49 onApprove: function (data, actions) {50 const { orderID } = data;51 return fetch('/api/paypal/orders/${orderID}/capture/', {52 method: "post",53 })54 .then((res) => {55 return res.json();56 })57 .then((orderData) => {58 // Redirect to success page59 });60 },61 inputEvents: {62 onChange: function (data) {63 // Handle a change event in any of the fields64 },65 onFocus: function(data) {66 // Handle a focus event in any of the fields67 },68 onBlur: function(data) {69 // Handle a blur event in any of the fields70 },71 onInputSubmitRequest: function(data) {72 // Handle an attempt to submit the entire card form73 // while focusing any of the fields74 }75 },76 });77 // Define the container for each field and the submit button78 const cardNameContainer = document.getElementById("card-name-field-container"); // Optional field79 const cardNumberContainer = document.getElementById("card-number-field-container");80 const cardCvvContainer = document.getElementById("card-cvv-field-container");81 const cardExpiryContainer = document.getElementById("card-expiry-field-container");82 const multiCardFieldButton = document.getElementById("multi-card-field-button");83 // Render each field after checking for eligibility84 if (cardField.isEligible()) {85 const nameField = cardField.NameField();86 nameField.render(cardNameContainer);87 const numberField = cardField.NumberField();88 numberField.render(cardNumberContainer);89 const cvvField = cardField.CVVField();90 cvvField.render(cardCvvContainer);91 const expiryField = cardField.ExpiryField();92 expiryField.render(cardExpiryContainer);93 // Add click listener to the submit button and call the submit function on the CardField component94 multiCardFieldButton.addEventListener("click", () => {95 cardField96 .submit()97 .then(() => {98 // Handle a successful payment99 })100 .catch((err) => {101 // Handle an unsuccessful payment102 });103 });104 }105 </script>106 </html>