fix: revalidateField does not trigger promise validation directly
kokoal opened this issue · comments
In some cases we want to validate a particular form field on an user action first without validating all form fields. And do final validation on fomr submit.
As for an exemple you have a promo code field you want to validate when the user click on a "Apply" button this will trigger a fetch
(with Promise
) validator
and only validate the field containing the promo code.
In this case I try using revalidateField
but it seems to not run the promise and always return true
.
My full example :
applyPromoCodeButton.addEventListener('click', clickApplyButton);
let promotionalCodeError = '';
const getPromotionalCodeError = () => {
return promotionalCodeError;
}
validation.addField(promotionalCodeField, [
{
validator: (code) => () => {
return new Promise((resolve) => {
if (code.length <= 0) {
resolve(true);
return;
}
const validatePromotionalCodeReadyUrl = validatePromotionalCodeUrl
.replace('{code}', code)
.replace('{orderNumber}', orderNumber);
fetch(validatePromotionalCodeReadyUrl)
.then(response => {
return response.json();
})
.then(validation => {
if (validation.valid === false) {
promotionalCodeError = validation.reason;
}
resolve(validation.valid);
});
});
},
errorMessage: getPromotionalCodeError,
}
]);
function clickApplyButton(event) {
// Deactivate form submission.
event.preventDefault();
// Manually trigger promotional code field validation.
validation.revalidateField(promotionalCodeField).then(isValid => {
// Do something more, eventually.
});
}
The only workaround I found is to use directly validateField
with afterInputChanged
at false
.
Like so :
validation.validateField(key, false).finally(() => {
validation.clearFieldStyle(key);
validation.clearFieldLabel(key);
validation.renderFieldError(key, true);
});
Do I did something wrong, or is that wanted from revalidateField
?
I think that the revalidateField method should perform all validation unconditionally because it is checked at a specific point the developer wants.
In my case, I want to perform asynchronous validation when focusing out of a specific tag, but I have a validation problem with the same problem.
The correct code I think is:
revalidateField(fieldSelector) {
if (typeof fieldSelector !== "string" && !isElement(fieldSelector)) {
throw Error(
`Field selector is not valid. Please specify a string selector or a valid DOM element.`
);
}
const key = this.getKeyByFieldSelector(fieldSelector);
if (!key || !this.fields[key]) {
console.error(`Field not found. Check the field selector.`);
return Promise.reject();
}
return new Promise((resolve) => {
// AS-IS
// this.validateField(key, true).finally(() => {
// TO-BE
this.validateField(key, false).finally(() => {
this.clearFieldStyle(key);
this.clearFieldLabel(key);
this.renderFieldError(key, true);
resolve(!!this.fields[key].isValid);
});
});
}