Custom validations
We’ve built a powerful API that allows you to hook into our forms’ validation system. Here’s how you add a custom validation to one of our forms:
// Wait until the form has initialized (it emits a 'cf:ready' event, and this function waits for that event)
CF.ready(function() {
var validation = {
comparator: function isValid(fieldValue) {
// if fieldValue is valid:
return true;
// if fieldValue is NOT valid:
return false;
},
// Display this error message if the comparator does not return true
errorMessage: 'Field value is not valid',
// If your comparator is asynchronous (if it returns a Promise,) set this to true.
// Otherwise, you don't need it. More on this below!
async: false,
};
var $form = document.querySelector('form[data-cf-form]');
// Add this validation to all fields with a data column key of "first_name"
$form.cfForm.addValidator(validation, 'first_name');
});
It’s important that you wait for the cf:ready
event before calling cfForm.addValidator
, because that functionality won’t be available until that event is fired. Using our handy CF.ready
function will do that for you!
Comparators
A comparator is a function that determines whether or not a fieldValue
is valid by returning true
or false
. There are two types of comparators you can implement:
- Synchronous
Synchronous comparators run instantaneous logic to determine whether or not a field value is valid. Use-cases for this involve sanitizing data and ensuring it is in the correct format.
Here’s an example that ensures the field value is an even number:
function isEven(fieldValue) {
return fieldValue % 2 == 0;
}
- Asynchronous
Asynchronous comparators can perform operations that are not instantaneous. Use-cases include: API requests, something that involves setTimeout
or setInterval
or anything else of that nature. This is accomplished by returning a Promise
in your comparator that resolves a boolean, true
if valid and false
otherwise. Check out this example comparator that uses fetch
to make an API request:
function isVerifiedByThirdPartyService(fieldValue) {
return new Promise(function(resolve, reject) {
fetch('https://some-service.com/verify?value=' + fieldValue)
.then(function(response) {
// If your service returns a JSON object in the response, you'll need to parse it:
return response.json();
})
.then(function(responseBody) {
if (responseBody.someData) {
// Field is valid.
resolve(true);
} else {
// Field is invalid.
resolve(false);
}
})
.catch(function(error) {
// Request failed. Probably some internal problem with the server.
// You should resolve(true) so that a broken service doesn't interfere
// with your form's submissions.
console.error('Bad response from server:', error);
resolve(true);
});
});
}
Don’t worry, both fetch
and Promise
are polyfilled!
Note
If you’re using an asynchronous comparator, make sure your validation has the
async: true
flag!
There are multiple benefits from using this:
- They don’t run unless all sychronous validations have passed, ensuring valid, safe data is sent to your service(s)
- Synchronous validations won’t be affected. Without the
async: true
flag, they will not show until all async validations have been evaluated, which can take seconds at a time - The field will display a spinner while validating, informing your customers that it’s waiting on something
Next up: Guides