Elements Methods & 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
ChangeEvent
s are emitted depending on the validation strategy set for each element; by default, validations run onBlur
. You can change this behavior by setting the boolean flag validateOnChange
to true
.
When running validations onChange
, elements emit events
whenever an error
occurs or if the input's value
changes. Default validation (onBlur
) triggers an event every time one of the values below changes:
{
"complete": false,
"valid": false,
"maskSatisfid": false,
"empty": false,
"errors": [
{...},
{...}
],
"cardBrand": "american-express",
"cardLast4": "8431",
"cardBin": "341212"
}
Attribute | Type | Eligible Elements | Description |
---|---|---|---|
complete | boolean | All | Whether the input valid and maskSatisfied properties are true . |
valid | boolean | All | Whether the input is valid according to validation for each element. Defaults to true if no validation is defined for the element. |
maskSatisfied | boolean | All | Whether the input satisfies the mask length requirements. Defaults to true if no mask is provided. |
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. |
cardBin | string | card cardNumber | (Optional) The credit card number's first 6 digits when the input is considered complete. |
If you need an eight digit BINs please email us at info@basistheory.com.
Metadata
Instead of subscribing to events, the same properties can be accessed at any time from the metadata
property on all elements.
Additionally, the card related event change events can be accessed from the cardMetadata
property only on Card and CardNumber elements.
Attribute | Eligible Elements | Attributes |
---|---|---|
metadata | All | complete , valid , maskSatisfied , empty |
cardMetadata | card cardNumber | cardLast4 , cardBin , cardBrand |
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 a session
})
.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 a session
})
.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 a session
})
.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 a session
})
.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 a session
})
.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.