Elements Method & Events
Basis Theory Elements offers several methods and events to listen to changes to your components and interact with the underlying data.
Methods
Once you have created and mounted an element instance, you can invoke the methods below:
<div id="my-card"></div>
<script>
var cardElement = BasisTheory.createElement("card");
cardElement.mount("#my-card");
cardElement.focus();
</script>
Name | Resulting Type | Eligible Elements | Description |
---|---|---|---|
clear | void | All | Clears the element input(s) value. |
focus | void | All | Focuses on the element input. |
blur | void | All | Blurs the element input. |
month | number | cardExpirationDate | Data-parsing method that resolves to the month value of the input date, where "January" = 1. |
year | number | cardExpirationDate | Data-parsing method that resolves to the four-digit year value of the input date. |
setValue | void | All | Accepts a synthetic reference from a retrieved token and safely sets it as the input value. |
Events
You can communicate with Elements by listening to events. When you subscribe to an event, you'll get back a Subscription that you can unsubscribe if/when it fits your workflow.
// Make sure to replace 'event-type' with an actual event type.
var subscription = cardElement.on("event-type", (event) => {
// handle event
});
subscription.unsubscribe(); // stops listening to the event type
On Ready
This event is triggered when the element has rendered and user is able to start interacting with it.
cardElement.on("ready", () => {
// handle ready event
});
On Change
This event is triggered whenever element's value(s) change. For example, if the user types data that doesn't change the state of a field between valid/invalid or empty/filled, you shouldn't expect the event to trigger.
cardElement.on("change", (changeEvent) => {
if (changeEvent.complete) {
// enable submit button
} else {
// disable submit button
// present validation message
}
});
Parameter | Required | Type | Description |
---|---|---|---|
event | true | "change" | The event type to listen to. |
handler | true | function | Callback function to be called when the event is fired. Takes in a ChangeEvent. |
ChangeEvent
{
"complete": false,
"empty": false,
"errors": [
{...},
{...}
],
"cardBrand": "american-express",
"cardLast4": "8431"
}
Attribute | Type | Eligible Elements | Description |
---|---|---|---|
complete | boolean | All | If the element value is well-formed and is ready to be submitted. |
empty | boolean | All | Whether the element is empty. Multi-input Elements will be empty only if all inputs are. |
errors | array | All | Array of FieldError. |
cardBrand | string | card cardNumber | (Optional) The credit card brand (e.g. 'american-express' , 'visa' , 'unknown' ). The value defaults to 'unknown' until a card brand is recognized. |
cardLast4 | string | card cardNumber | (Optional) The credit card's last 4 digits. The value is not provided until a complete card number is entered. |
FieldError
{
"targetId": "cardNumber",
"type": "invalid"
}
Attribute | Type | Description |
---|---|---|
targetId | string | Input ID that triggered the error. Values vary per element type. |
type | "invalid" or "incomplete" | Type of the error. |
On Focus
Triggered when an element input is focused.
cardElement.on("focus", (focusEvent) => {});
Parameter | Required | Type | Description |
---|---|---|---|
event | true | "focus" | The event type to listen to. |
handler | true | function | Callback function to be called when the event is fired. Takes in a FocusEvent. |
FocusEvent
{
"targetId": "cardNumber"
}
Attribute | Type | Description |
---|---|---|
targetId | string | Input ID that triggered the event. Values vary per element type. |
On Blur
Triggered when an element input focus is lost.
cardElement.on("blur", (blurEvent) => {});
Parameter | Required | Type | Description |
---|---|---|---|
event | true | "blur" | The event type to listen to. |
handler | true | function | Callback function to be called when the event is fired. Takes in a BlurEvent. |
BlurEvent
{
"targetId": "cardNumber"
}
Attribute | Type | Description |
---|---|---|
targetId | string | Input ID that triggered the event. Values vary per element type. |
On Keydown
Triggered when user hits a special key inside an element input.
cardElement.on("keydown", (keydownEvent) => {});
Parameter | Required | Type | Description |
---|---|---|---|
event | true | "keydown" | The event type to listen to. |
handler | true | function | Callback function to be called when the event is fired. Takes in a KeydownEvent. |
KeydownEvent
{
"targetId": "cardNumber",
"key": "Enter",
"ctrlKey": false,
"altKey": false,
"shiftKey": false,
"metaKey": false
}
Attribute | Type | Description |
---|---|---|
targetId | string | Input targetId that triggered the event. Values vary per element type. |
key | Escape or Enter | Key pressed by the user. |
ctrlKey | boolean | Flag indicating control key was pressed when the event occurred. |
altKey | boolean | Flag indicating alt key was pressed when the event occurred. |
shiftKey | boolean | Flag indicating shift key was pressed when the event occurred. |
metaKey | boolean | Flag indicating meta key was pressed when the event occurred. |
Tokenization
Elements' values can be securely tokenized using tokens.create
and tokenize
services. To do that, simply pass the Element instance (or one of its data parsing methods) in the payload.
You can fetch this same data later with Get a Token API
BasisTheory.tokens
.create({
type: "token",
data: {
sensitiveData: sensitiveDataElement,
nonSensitiveData: "plainText", // see warning on plain text data
otherData: {
someInteger: 20,
someBoolean: false,
},
someOtherData: ["plainText1", "plainText2"],
},
metadata: {
nonSensitiveField: "nonSensitiveValue",
},
})
.then((token) => {
console.log(token.id); // token to store
console.log(JSON.stringify(token)); // full response
});
BasisTheory.tokens
.create({
type: "card",
data: cardElement,
})
.then((token) => {
console.log(token.id); // token to store
console.log(JSON.stringify(token.data)); // redacted card data
});
BasisTheory.tokens
.create({
type: "bank",
data: {
routingNumber: routingNumberElement,
accountNumber: accountNumberElement,
},
})
.then((token) => {
console.log(token.id); // token to store
console.log(JSON.stringify(token.data)); // redacted bank data
});
BasisTheory.tokenize({
card1: {
type: "card",
data: cardElement,
},
card2: {
type: "card",
data: {
number: cardNumberElement,
expiration_month: cardExpirationDateElement.month(),
expiration_year: cardExpirationDateElement.year(),
cvc: cardVerificationCodeElement,
},
},
sensitiveData: sensitiveDataElement,
nonSensitiveData: "plainText", // see warning on plain text data
otherData: {
someInteger: 20,
someBoolean: false,
},
someOtherData: ["plainText1", "plainText2"],
}).then((tokens) => {
console.log(tokens.card1.id, tokens.card2.id, tokens.sensitiveData); // token to store
console.log(JSON.stringify(tokens)); // full response
});
The actual input data never leaves the element (iframe) other than to hit our secure API endpoints.
When submitting plainText
values, data will be HTML encoded before storage for security reasons.
Errors
Elements services could throw an error based on client-side validations or if the server rejects the request.
import {
BasisTheoryApiError,
BasisTheoryValidationError,
} from "@basis-theory/basis-theory-js/common";
BasisTheory.tokenize({
card1: {
type: "card",
data: cardElement1,
},
card2: {
type: "card",
data: cardElement2,
},
ssn: textElement,
}).catch((error) => {
if (error instanceof BasisTheoryValidationError) {
// check error details
} else if (error instanceof BasisTheoryApiError) {
// check error data or status
}
});
BasisTheoryValidationError
{
details: {
card1: {
number: {
type: 'invalid'
},
cvc: {
type: 'incomplete'
}
},
card2: {
}
},
validation: [] // deprecated
}
Attribute | Type | Description |
---|---|---|
name | string | Error name, always 'BasisTheoryValidationError' . |
details | object | Maps payload properties to their respective element's validation problems. |
BasisTheoryApiError
{
data: {
// API response body
},
status: 400
}
Attribute | Type | Description |
---|---|---|
name | string | Error name, always 'BasisTheoryApiError' . |
data | object | Response body sent from the server. |
status | number | Response HTTP status. |
Error name
property may be used instead of checking its instance type.
Detokenization
Elements' values can be securely revealed using the tokens.retrieve
service and the Elements' setValue
method. When retrieve
is called from a Basis Theory instance configured with elements: true
, the API request is made from inside a Basis Theory hosted iframe
and the returned data remains within it.
const textElement = BasisTheory.createElement("text", {
targetId: "text-element",
});
BasisTheory.tokens
.retrieve("ca9f3fd7-3906-4087-83aa-9a6129221297", {
apiKey: "key_N88mVGsp3sCXkykyN2EFED", // api key is required and should belong to an 'expiring' application
})
.then((token) => {
textElement.setValue(token.data);
});
const cardElement = BasisTheory.createElement("card");
BasisTheory.tokens
.retrieve("ca9f3fd7-3906-4087-83aa-9a6129221297", {
apiKey: "key_N88mVGsp3sCXkykyN2EFED", // api key is required and should belong to an 'expiring' application
})
.then((token) => {
cardElement.setValue(token.data);
});
// or
BasisTheory.tokens
.retrieve("ca9f3fd7-3906-4087-83aa-9a6129221297", {
apiKey: "key_N88mVGsp3sCXkykyN2EFED", // api key is required and should belong to an 'expiring' application
})
.then((token) => {
cardElement.setValue({
number: token.data.number, // expects string
expiration_month: token.data.expiration_month, // expects number
expiration_year: token.data.expiration_year, // expects number
});
});
const cardNumberElement = BasisTheory.createElement("cardNumber", {
targetId: "card-number",
});
const cardExpirationDateElement = BasisTheory.createElement(
"cardExpirationDate",
{ targetId: "card-expiration-date" }
);
BasisTheory.tokens
.retrieve("ca9f3fd7-3906-4087-83aa-9a6129221297", {
apiKey: "key_N88mVGsp3sCXkykyN2EFED", // api key is required and should belong to an 'expiring' application
})
.then((token) => {
cardNumberElement.setValue(token.data.number);
cardExpirationDateElement.setValue({
month: token.data.expiration_month,
year: token.data.expiration_year,
});
});
The data
attribute in the token returned by the retrieve
method is not the actual data, but a a synthetic representation of the sensitive detokenized data.
Token attributes such as metadata
are directly accessible from the retrieve
response as they are considered non-sensitive.
Errors
Elements services will throw an error if the server rejects the request.
import { BasisTheoryApiError } from "@basis-theory/basis-theory-js/common";
BasisTheory.tokens
.retrieve("ca9f3fd7-3906-4087-83aa-9a6129221297", {
apiKey: "key_N88mVGsp3sCXkykyN2EFED", // api key is required and should belong to an 'expiring' application
})
.catch((error) => {
if (error instanceof BasisTheoryApiError) {
// check error details
}
});
BasisTheoryApiError
{
data: {
// API response body
},
status: 400
}
Attribute | Type | Description |
---|---|---|
name | string | Error name, always 'BasisTheoryApiError' . |
data | object | Response body sent from the server. |
status | number | Response HTTP status. |
Error name
property may be used instead of checking its instance type.