Hello fellow developers and VeloPers
Did you find yourself in a case where you want to validate an input field, but the validation needs to run on the backend, perhaps to check with 3rd party services? For example, checking if the entered IBAN is a valid one? Or if an email address exists in your external database? If your answer is YES , you should keep reading this example.
In this example, you’ll learn how to asynchronously validate an input field and only enable the form’s submit button when the field’s value is valid.
Disclaimer : This is NOT a perfect solution, but more of a workaround that I personally use in my projects.
In this example, we’re going to check if an email exists in our database , and mark the email as invalid if it doesn’t.
To see a live example, open the demo website here .
There are 4 steps to do it, click on the step to directly scroll to it.
-
Basic Requirements .
-
Writing the input field’s validations .
-
Triggering the validation on each input .
-
Validating the email (Backend) .
Step #1 : Basic Requirements
Before we start our project, let’s define our elements’ selectors, and a cache variable to store some data.
const $email = $w('#email');
const $submit = $w('#submitBtn'); // The form's submit button
const $error = $w('#errorMsg'); // A text element to show errors
const cache = {
timer: { func: null, duration: 500 },
checking: false,
email: { value: null, isValid: false },
valid_emails: [],
onBeforeValidation: () => {
// A function to run before the validation take place
$submit.disable();
$error.collapse();
cache.checking = true;
cache.email.value = null;
cache.email.isValid = false;
},
onAfterValidation: (result, email) => {
// A function to run after the validation is done
if (result.valid) {
cache.email.isValid = true;
cache.email.value = email;
if (!cache.valid_emails.includes(email)) {
cache.valid_emails.push(email);
}
} else {
$error.text = $email.validationMessage;
$error.expand();
}
cache.checking = false;
}
}
Step #2: Writing the input field’s validations.
The first thing we need to do is create our email validator, and pass it to the input’s onCustomValidations() event handler.
$email.onCustomValidation((email, reject) => {
cache.onBeforeValidation();
if (typeof email === 'string') {
if (!cache.valid_emails.includes(email)) {
return new Promise((resolve, reject) => {
if (cache.timer.func) {
clearTimeout(cache.timer.func);
cache.timer.func = null
}
cache.timer.func = setTimeout(() => {
/* validateEmail is a backend function imported
to this page, we'll create it in step #4. */
validateEmail(email).then(result => resolve(result));
}, cache.timer.duration);
}).then((result) => {
if (!result.valid) { reject(result.message) }
cache.onAfterValidation(result, email);
return;
})
} else {
cache.onAfterValidation({ valid: true }, email);
}
} else {
reject('Please enter your email address.');
cache.onAfterValidation({ valid: false });
}
})
Step #3: Triggering the validation on each input.
Even though the validation is triggered on input, the validated value isn’t the most recent one, it’ll always validate the previous value of the input field, for example, when type in the first character in the input field, the value passed to the validation function from the event handler is an empty string, to overcome this issue, we need to rewrite the entered value each time an input is made to make sure the validation function uses the most recent value on the input field.
$email.onInput(event => {
const value = event.target.value; // Getting the latest value;
event.target.value = value; // Overwriting the value;
})
Step #4: Validating the email (Backend).
To validate the email address (securely), we need to create/use a backend web module (.jsw). If you’re not familiar with it please read this article from Wix.
In our function, and for the simplicity of the example, we won’t connect to a 3rd party service to validate the email, we’ll just use a timeout to simulate the duration of a 3rd party service, and validate the emails against a local array in the module.
export validateEmail(email) {
if (!email) {
return Promise.reject('Pleaes provide an email first.');
}
// Array of predefined (valid) emails;
const emails = ['contact@nasriya.net', 'support@nasriya.net'];
return new Promise((resolve) => {
setTimeout(() => {
if (emails.includes(email)) {
resolve({ valid: true });
} else {
resolve({ valid: false });
}
}, 1e3);
})
}
That’s it for the example, happy to hear your feedback about it in the comments below.
Notes:
- Please don’t comment asking for help to implement this on your website, if you need professional help you can either visit our support page or find a developer on the Marketplace.
- If you find this helpful and you’d like to support us, please click here.
Hope this helps!~
Happy Coding
Ahmad - Nasriya Software.