Pristine
Pristine copied to clipboard
Custom Validator with Promise / XHR Requests ("Timeouts") are not working / always false
Hej,
i try to check the input against an API / XHR Request and output the error according to the response as true or false.
I’ve tried it with a simple Timeout within one of the demos: https://codepen.io/Maybach/pen/mdEQjWN
When you remove the setTimeout on line 12, then it works. The timeout simulates my XHR request (which takes time / is a Promise).
What i’m trying to do: Only when the input is valid (an e-mail), then send the XHR request. XHR Request response with a 200 or 409. If 200, the input is valid / free username. If 409 the e-mail is already registered and want to tell this the user.
pristine.addValidator(
emailField,
function (value) {
if (!this.validity.typeMismatch) { // Check if HTML5 says its a valid input → maybe do this with Pristine as well
makeRequest({
method: "GET",
url:
"REQUESTURL?username=" +
value
})
.then(function (data) {
return true;
})
.catch(function (err) {
console.log(err);
return false;
});
}
return false;
},
"E-Mail already registered, want to Login?",
2,
true
);
(makeRequest is just a simple XHR Request which returns a Promise → this works)
since its a async function aka timeout/promise it should be used as such. (sorry i’m new to promises haha)
But its still not working. I never geht the error shown.
pristine.addValidator(
emailField,
async function (value) {
let success;
if (!this.validity.typeMismatch) { // Check if HTML5 says its a valid input → maybe do this with Pristine as well
try {
success = await makeRequest({
method: "GET",
url:
"REQUESTURL?username=" +
value
});
}
catch {
success = false;
}
}
return success; // Waits till makeRquest is resolved and return the value (true/false) ← THIS IS NOT WORKING
},
"E-Mail already registered, want to Login?",
2,
true
);
Facing the same issue, watching closely!
Adding an error in a promise is not working too. I built a working to add my error and it works, but when an error is added within a promise, the pristine.validate()
returns true.
but there are the errors in the fields within the
pristine
object
Almost a year later and I'm facing the same issue. @Maybach91 just wondering did you ever figure out a work around?
Almost a year later and I'm facing the same issue. @Maybach91 just wondering did you ever figure out a work around?
@Nevario
Looking at my own 1 year old code, i can only give it to you, but cannot explain all the reasons behind this anymore. But maybe it helps. Basically i swap the logic and handling errors within the Promise instead of use the built in async validation of pristine.addValidator
.
// ------------------
// E-Mail API Request
// ------------------
// Checks if the EMAIL is already registered on the API endpoint
const debug = true; // logs everything whats happening
const checkUsernameApiUrl = 'YOUR_API_URL'; // your api url to check the form data against to
const loginUrl = 'LOGIN_URL'; // url to the login page. if email is already registered it shows a hint to directly login instead
// Init a timeout variable to be used for email check
let timeout = null;
const checkEmailExistence = (email) => {
const fieldParent = emailField.parentNode;
return new Promise(function (resolve, reject) {
// Clear the timeout if it has already been set.
// This will prevent the previous task from executing
// if it has been less than <MILLISECONDS>
clearTimeout(timeout);
// Make a new timeout set to go off in 1000ms (1 second)
timeout = setTimeout(function () {
makeRequest({
method: "GET",
url: checkUsernameApiUrl + encodeURIComponent(email)
}).then(response => {
if (response.length) {
debug &&
console.info(
`%c ${email} is available`,
"color: #009d55; background-color:#c4eac1"
);
fieldParent.classList.remove('is-loading');
fieldParent.classList.add('is-successful');
setTimeout(function () {
fieldParent.classList.remove('is-successful');
}, 2000);
resolve(true);
} else {
debug &&
console.error(`%c ${email} is not available`, "color: #d60202");
pristine.addError(
emailField,
`E-Mail already registered, <a target="_blank" href="${loginUrl}">Login</a>?`
);
fieldParent.classList.remove('is-loading');
reject(false);
}
}).catch((err) => {
if (err.status === 409) {
debug && console.error(`%c ${email} is not available`, "color: #d60202");
pristine.addError(
emailField,
`E-Mail already registered, <a target="_blank" href="${loginUrl}">Login</a>?`
);
fieldParent.classList.remove('is-loading');
reject(false);
} else {
if (debug) {
console.group("Server Error");
console.info(
"Server not reachable, blocked because of CORS policy, try setting a proxy?"
);
console.error(err);
console.groupEnd();
}
fieldParent.classList.remove('is-loading');
reject(err);
throw new Error(
"Server not reachable, blocked because of CORS policy, try setting a proxy?",
err
);
}
});
}, 400);
});
}
@Maybach91 Thank-you very much. This was incredibly helpful in getting me to a solution!