Reputation: 864
I currently have a jQuery method that validates a UK phone number. This only validates the format and does not make sure the number is real, so I am trialing a telephone validation service that will.
The code below shows the jQuery validation method with the final IsValid(phone_number, 'GB') bit calling a function which deals with the service.
jQuery.validator.addMethod('phonesUK', function(phone_number, element) {
phone_number = phone_number.replace(/\(|\)|\s+|-/g,'');
return this.optional(element) || phone_number.length > 8 &&
phone_number.match(/^(?:(?:(?:00\s?|\+)44\s?|0)(?:1\d{8,9}|[23]\d{9}|8\d{7,9}|7(?:[45789]\d{8}|624\d{6})))$/)
&& IsValid(phone_number, 'GB');}, 'Please specify a valid UK phone number');
The code below handles calling the service and works fine on its own.
function IsValid(telephoneNumber, defaultCountry)
{
var internationaltelephonevalidation = new data8.internationaltelephonevalidation();
internationaltelephonevalidation.isvalid(
telephoneNumber,
defaultCountry,
[
new data8.option('UseMobileValidation', 'true'),
new data8.option('UseLineValidation', 'true')
],
showIsValidResult
);
}
function showIsValidResult(result) {
if (!result.Status.Success) {
alert('Error: ' + result.Status.ErrorMessage);
}
else {
if(result.Result.ValidationResult == "Invalid"){
return false;
}else{
return true;
}
}
}
My problem is that the jQuery validator method returns false before the response from the service comes back.
I did try a set timeout in the jQuery method and set a variable before returning from the showIsValidResult() function, but the variable was always undefined.
Any ideas please?
Thanks
Upvotes: 1
Views: 506
Reputation: 3515
internationaltelephonevalidation.isvalid
is an async XHR call. It's being executed within the IsValid
function but the function doesn't wait for the response. Instead it simply returns undefined
because it is a default return statement in JavaScript.
The isValid
function can be rewritten using the $.Deferred object:
var funReady;
function IsValid(telephoneNumber, defaultCountry) {
funReady = new $.Deferred();
var internationaltelephonevalidation = new data8.internationaltelephonevalidation();
internationaltelephonevalidation.isvalid(
telephoneNumber,
defaultCountry,
[
new data8.option('UseMobileValidation', 'true'),
new data8.option('UseLineValidation', 'true')
],
showIsValidResult
);
$.when(funReady).then(function() {
// no action needed after $.Deferred is resolved/rejected.
// just waiting for it to happen without leaving isValid
// function ...
});
return funReady.state() === "resolved" ? true : false;
}
function showIsValidResult(result) {
if (!result.Status.Success) { // http(s) request failed
funReady.reject();
}
if(result.Result.ValidationResult == "Invalid") {
funReady.reject();
} else {
funReady.resolve();
}
}
Deferred object returns a promise. By default its status is "pending", that means neither "resolved" (success) nor "rejected" (fail). While a promise is in "pending" state, $.when()
function waits for its status to change to either "resolved"/"rejected".
The Deferred status is changed programmatically once the async XHR request is finished/failed.
This solution is a demo. You should consider checking if the $.Deferred
is already created, instead of re-creating new instances for each isValid
call. There could be other edge cases in this proposal but it should help you get to the right answer.
Upvotes: 1