html5 validate form with required="true" and custom check - javascript

What I'm looking for: way to have innate html 5 form validation using the required="true", where if the user clicks the "Submit" button, the first thing that happens is the automatic html 5 validation where it checks to see if "username" is provided by the user. If it's not, then it displays the ugly error bubble.
If it is provided, however, I then have my own custom validation for checking against the db if the username exists. If it does, then return true (allow submission), false otherwise. What's happening: the form is getting submitted. It's like it does not wait for the success callback to return true/false on whether or not it should be submitted.
I hope that's clear enough! Code below:
html:
<form>
<input type="text" required="true" id="username" />
<button type="submit">Submit</button>
</form>
js:
$("form").submit(function() {
$.ajax({
url: 'usernamechecker.php?username=' + $("#username").val(),
success: function(resp) {
if (!resp.UsernameExists) {
return true; // allow form submission
}
return false; // do not allow form submission
}
});
});

You can't return a value through a callback like that. The callback for "success" won't run until the "ajax" call has completed, long after the "submit" handler has already returned.
Instead of that, I'd just do the submit and let it return with an error if there are server-side issues (like "username in use" or whatever). There's no point making two round-trips. If there are no problems, it can just complete the operation and return whatever results page you want.

You need to add "async: false" as a parameter to your ajax call in order to force the call to finish before continuing on with the rest of the code.
$("form").submit(function(event) {
$.ajax({
async: false,
url: 'usernamechecker.php?username=' + $("#username").val(),
timeout: 1000,
success: function(resp) {
if (resp.UsernameExists) {
event.preventDefault(); // do not allow form submission
},
error: function() {
//fall back code when there's an error or timeout
},
});
});

Related

Validate a simple HTML form via JSON answere

I´am a UX designer and one of these JS dummie/"HTML coder" guys.
I need help or a hint to validate a simple HTML form via a second request which returns a JSON answere, before the form is send.
I have a really simple HTML form on a landingpage where the user can enter a coupon code:
<form id="tokensubmit" method="GET" action="https://www.xyz/cart.html">
<div class="form-group">
<input type="text" name="tokenCodeAdd" id="tokenCodeAdd" size="25" value="" class="form-control input-lg" placeholder="Please enter Coupon Code">
</div>
<input id="input_id" type="submit" class="btn btn-lg btn-warning btn-block" value="Submit">
</form>
If a user enters his Coupon code and hit the submit button, the code will be added to the action URL (https://www.xyz/cart.html) and the User is redirected to this cart.html page. If the coupon code is correct everything is fine. If not he receives an error message on the cart.html page.
So far so good.
BUT: I want to validate the coupon code without redirecting the user to a new website(cart.html).
The system offers a second URL for this already. A url like:
/checkout/validate.html?tokenCode=12345678
This returns a JSON answere with a status like:
{"error":"Wrong Coupon Code."}
if the Coupon code isnt right.
If it is valid, something like:
{"error":"null"}
returns.
What I am searching for is a simple solution to call the validation URL (validation.html) first on click on the "submit" button, parse the returning JSON, prevent the form from sending if "error" is something else than "null" and print the JSON message ("Wrong Coupon Code.") right above the form input.
If "error" = "null" the forms behavior should not change. It should just open the https://www.xyz/cart.html URL with the tokenCode attached as parameter.
What I´am trying/starting with looks like:
$('#tokensubmit').submit(function(event){
event.preventDefault();
var tokenCheck = $(this).find('input[id="tokenCodeAdd"]').val();
$.ajax({
url: '/checkout/validate.html'+tokenCheck,
type: 'GET',
success: function(data){
var jsonData = $.parseJSON(data);
}
});
});
Its just the beginning, I know. The real parsing part is missing and the error message output if the validation fails, or the redirect if not.
Anyone who could help?
And thx in advanced!
Small hint: The form is placed on a WordPress driven landingpage, so PHP and JQuery is an option.
The code you have for getting the validation is almost correct:
$('#tokensubmit').submit(function(event){
event.preventDefault();
var tokenCheck = $(this).find('input[id="tokenCodeAdd"]').val();
$.ajax({
// either attach the parameter like you are trying to do directly to the url,
// but in this way:
url: '/checkout/validate.html?tokenCode='+tokenCheck,
// or give the URL parameter(s) as data object to jQuery:
data: {
tokenCode: tokenCheck
}
type: 'GET',
// if you specify the dataType you want to receive as json,
// jQuery will parse it for you already
dataType: 'json',
success: function(data){
// now you can check the data for error or not, for example like:
if(data.error == null){
// do something (most likely REALLY submit the form now?)
}else{
alert('tokenCode invalid');
}
}
});
});
With jquery you can send through a data parameter and it will work out how to place it in the URL:
$.ajax({
url: '/checkout/validate.html',
type: 'GET',
data: {"tokenCode": tokenCheck}
success: function(data){
var jsonData = $.parseJSON(data);
}
});
I would also advise not doing an Ajax request at all if tokenCheck is empty.
Wouldn 't it be easier to check the coupon code when the user leaves the input field? First the example while submitting the whole form.
$('#tokensubmit').on('submit', function(event) {
event.preventDefault();
var validationSuccess = false;
$.ajax({
url : '/checkout/validate.html',
type : 'GET',
data : { tokenCode : $('#tokeninput').val() }
success : function(response) {
var data = $.parseJSON(response);
if (data.error === null) {
validationSuccess = true;
}
}
if (validationSuccess === true) {
$('#tokensubmit').off('submit').submit();
}
});
So what we 've done here? The submit event listener is nearly the same you 've done. We prevent the default submitting of the form and do an ajax request for validation the input value. If the request returns no error as response, we simply unbind the submit event listener from the form and submit the form again.
In my opinion it would be better to work with the blur event listener on the input field. In combination you could use the HTML5 Constraint Validation API. So you don 't have to submit the form and the ajax request would be done on blurring the input field. I think that would be the better user experience.
So here 's the blur event listener:
<input type="text" name="the-input-field" id="the-input-field" value="" required>
$('#the-input-field').on('blur', function(event) {
var element = this;
$.ajax({
url : '/checkout/validate.html',
type : 'GET',
data : { tokenCode : element.val() }
success : function(response) {
var data = $.parseJSON(response);
if (data.error !== null) {
element.setCustomValidity('Your input is invalid!');
// place some error message elsewhere in the markup
} else {
element.setCustomValidity('');
}
}
});
});
First we placed the required Attribute in the input element. It marks the input element as required. So if it 's empty you could not submit the form. Then we placed the blur event listener, which is doing the ajax request. If the response is false, we place a custom error via setCustomValidity. It is a native HTML5 Constraint Validation API function. If the custom error on the input element is set, you could not submit the form. If the user enters another token the request is done again on leaving the input element. If the token is valid, the custom error message will be removed and the form can be submitted.

Determining duplicate values before a form is submitted

Say I have an online form, and I want to figure out whether a user is entering an email that's already in use by the system. Can I tell the system to check the field against the database as soon as the user moves their cursor / selection away from the field? Could anyone point me in the right direction if this is actually possible?
You could attach a listener to the text field using jQuery's blur event, like so:
$('#MyEmailField').blur(function() {
// jQuery AJAX Call here, $.ajax(...)
})
For this You need to call ajax when user writing an email id means on blur event as below :
$('#yourfieldID').blur(function() {
var val = $(this).val();
$.ajax({
type: 'POST',
url: 'your url',
data: {email: val},
success: function (data) {
// check for response
});
}
});
});
Now In file which you called in ajax url, Your need to check data which is exist in database or not and according to that you need to send response and check it in sucess part of ajax call.
I hope you will get it.
Yes, it is possible using an AJAX call on the "onblur" event of Javascript (or "focusout" method of jQuery)
You could use something like this, in the HTML:
<input type="email" name="myinput" />
And the JS:
$( "input" ).focusout(function() {
var usr_email = $(this).value;
$.ajax({
method: "GET",
url: "some.php",
data: { email: usr_email }
}).done(function( response ) {
if(response == "taken"){
$("input").borderColor = "red";
}
});
}
You can check for email's availability through an Ajax call in database on text change or blur event of email textbox. Then notify the user accordingly.
As soon as user moves out of email field, say tab or mouse click, you need to trigger a function to make a Ajax call to your server. The triggering function would be onBlur of email field. Then check If user email exits, get back Ajax response to notify the user.

event.preventDefault(); not working in ajax

I am firing an ajax call on a signup form wherein i am checking whether the email id entered by the user has already been used or not.
Ajax Function :
<script>
$( "#becomesignup" ).submit(function( event ) {
$.ajax({
url : 'login', // Your Servlet mapping or JSP(not suggested)
data : {"email":$("#becomeemail").val()},
type : 'GET',
dataType : 'html', // Returns HTML as plain text; included script tags are evaluated when inserted in the DOM.
success : function(response) {
if(response == "true"){
$('#emailerrorbecome').slideDown();
$('#become-submit').prop('disabled', true);
event.preventDefault();
}else{
$('#emailerrorbecome').slideUp();
$('#become-submit').prop('disabled', false);
}
$('.black-screen').hide();
},
error : function(request, textStatus, errorThrown) {
alert(errorThrown);
}
});
});
</script>
In the above ajax function, if the response is true then the email id is already been used and i need to show an error div($('#emailerrorbecome').slideUp();) and then prevent the form to get submitted. But even event.preventDefault() is not working causing the emaild id to be registered again.
Please help me with this. TIA
You should submit the form programatically and always preventing default behaviour in jq submit handler. E.g, using context and calling submit() DOM API method:
$("#becomesignup").submit(function(event) {
event.preventDefault(); /* prevent form submiting here */
$.ajax({
context: this, /* setting context for ajax callbacks*/
url: 'login', // Your Servlet mapping or JSP(not suggested)
data: {
"email": $("#becomeemail").val()
},
type: 'GET',
dataType: 'html', // Returns HTML as plain text; included script tags are evaluated when inserted in the DOM.
success: function(response) {
if (response == "true") {
$('#emailerrorbecome').slideDown();
$('#become-submit').prop('disabled', true);
$('.black-screen').hide(); /* hide it here */
} else {
$('#emailerrorbecome').slideUp();
$('#become-submit').prop('disabled', false);
this.submit(); /* 'this' refers to the FORM, and calling submit() DOM native method doesn't fire again jq handler */
}
},
error: function(request, textStatus, errorThrown) {
alert(errorThrown);
}
});
});
For explanation of the why, see Quentin's answer
You cannot prevent the submit long after the submit function has returned. The Ajax result occurs much later.
You can instead flag the submit (e.g. use a sentinel variable) and cancel it unless allowed. Then trigger a submit from code in the Ajax callback.
Example:
var allowSubmit = false;
$( "#becomesignup" ).submit(function( event ) {
if (!allowSubmit){
$.ajax({
url : 'login', // Your Servlet mapping or JSP(not suggested)
data : {"email":$("#becomeemail").val()},
type : 'GET',
dataType : 'html', // Returns HTML as plain text; included script tags are evaluated when inserted in the DOM.
success : function(response) {
if(response == "true"){
$('#emailerrorbecome').slideDown();
$('#become-submit').prop('disabled', true);
// Enable next submit to proceed
allowSubmit = true;
// And trigger a submit
$( "#becomesignup" ).submit();
}else{
$('#emailerrorbecome').slideUp();
$('#become-submit').prop('disabled', false);
}
$('.black-screen').hide();
},
error : function(request, textStatus, errorThrown) {
alert(errorThrown);
}
});
}
// return false does e.preventDefault(), and true allows it to proceed
return allowSubmit;
});
You are calling preventDefault to late.
Order of execution is this:
Event handler fires
HTTP request is sent
Event handler finishes
Prevent Default was not called so the default behaviour occurs
HTTP response is recieved
Success handler fires
Prevent Default is called … too late to have any effect
You can't wait for the HTTP response to come back before preventing the default behaviour.
You either need to always prevent the default behaviour and then conditionally resubmit the form with JS in the submit handler, or move the logic for when you use Ajax to perform your tests so it doesn't depend on the form submission event in the first place (e.g. run it as soon as the data has been entered and be prepared for the possibility that the form might get submitted before your JS has finished running).
you can make use of return false instead of eventPreventDefault.
I had been using the location.reload() as a dirty hack to refresh the page to prevent submission, but return false works well even without a refresh, it doesn't submit the form.

How to continue form submission after an AJAX call?

I want to validate user entries on a WordPress post upon hitting the submit button, display an error message is there are problems, and submit the form if everything is OK. I have a PHP function that does the checking, returning true if data in form_data is OK, some error code otherwise. The following JavaScript issues the AJAX request, and was supposed to continue submitting the form upon successful checking, but it doesn't:
jQuery(document).ready(function() {
jQuery('#post').submit(function() {
var form_data = jQuery('#post').serializeArray();
var data = {
action: 'ep_pre_submit_validation',
security: '<?php echo wp_create_nonce( 'pre_publish_validation' ); ?>',
form_data: jQuery.param(form_data),
};
var proceed = false;
jQuery.post(ajaxurl, data, function(response) {
if (response.indexOf('true') > -1 || response == true) {
proceed = true;
} else {
alert("Error: " + response);
proceed = false;
}
});
jQuery('#ajax-loading').hide();
jQuery('#publish').removeClass('button-primary-disabled');
return proceed; //breakpoint here makes the code run
});
});
The code is adapted from a WPSE question, which originally didn't work for me as the form didn't get submitted. I found out that if the jQuery function bound to .submit() returns true, the form should be submitted, so that's what I tried to implement. With the code above, it doesn't seem to work at first (form doesn't get submitted when there are no errors), but upon close inspection with Firebug proceed seems to get the right result if a breakpoint is inserted at the return proceed line. It works as intended with valid data only if I wait it out a bit upon hitting the breakpoint, and then continue execution. If there are errors, the alert is issued without a problem.
What is the best way to handle this?
EDIT
Based on #Linus answer below, the following code works with both valid and invalid data:
jQuery(document).ready(function() {
jQuery('#post').submit(function() {
if(jQuery(this).data("valid")) {
return true;
}
var form_data = jQuery('#post').serializeArray();
var data = {
action: 'ep_pre_submit_validation',
security: '<?php echo wp_create_nonce( 'pre_publish_validation' ); ?>',
form_data: jQuery.param(form_data),
};
jQuery.post(ajaxurl, data, function(response) {
if (response.indexOf('true') > -1 || response == true) {
jQuery("#post").data("valid", true).submit();
} else {
alert("Error: " + response);
jQuery("#post").data("valid", false);
}
//hide loading icon, return Publish button to normal
jQuery('#ajax-loading').hide();
jQuery('#publish').removeClass('button-primary-disabled');
});
return false;
});
});
Short answer: You can't - not in this manner.
Some background: The callbacks you supply as arguments to functions such as $.post are executed asynchronously. This means that you will return proceed before your success callback has been executed, and proceed will always be false. With your breakpoint, if you wait until the success callback has executed, proceed will be true and all will be well.
So, if you want to submit the form after your ajax request has finished, you must submit it using javascript. This is pretty easy with jQuery, just do a jQuery $.post with data: $("yourForm").serialize() and url: yourForm.action.
This is basically what you already are doing, you just have to repeat that call to the URL to which you actually want to post the data.
EDIT:
Another way would be to set an attribute on your form, say valid, and in your submit handler check that:
jQuery("#post").submit(function() {
if($(this).data("valid")) {
return true;
}
// Rest of your code
});
And in the success callback for your validation ajax request you would set/clear that attribute, and then submit:
$("#post").data("valid", true).submit();
EDIT:
You also want to do your "ajax-loading"/button enabling inside the callback for $.post for the same reasons stated above - as it is, they will happen immediately, before your ajax call returns.
Bind your button to a validation function instead of submit. If it passes validation, call submit().
Wordpress has its own mechanism to process Ajax requests, using wp-admin/wp-ajax.php. This allows you to run arbitrary code on either side of the Ajax boundary without having to write the back and forth status-checking code and all that. Set up your callbacks and go....
The real question is - why are you doing validation server-side? Why can't you load in the validation criteria before - as the post is being written? Then your validation can happen real-time and not on-submit.
jquery.post is performed asynchronously, which means the JS will continue before it gets the reply. You're stuck with Diodeus's answer - bind the button to validtion which then submits the form (which makes it not degrade well), or change your $.post to ajax and turn off async, which will force it to wait for response before proceeding...possibly locking up JS on your page until it times out.
$.ajax({
type: 'POST',
url: ajaxurl,
async:false,
data: data,
timeout:3000,
success: function(){
}
});

Using return true or return false on a link with target blank in jQuery

I have a form that has target="_blank"on submit.
I want to validate the form however, prior to it launching the new window. I could use window.open instead, but then it can be blocked by popup blockers.
The problem I'm having is the validation uses ajax and the time it takes to get the response for return false, is too long and it opens the new window.
$('.submit').click(function(){
$.post("/ajax/save/", { state: $('.state_field').val() },
function(data) {
if(data == 'false'){
alert('invalid state');
return false;
}else{
return true;
}
}
);
});
Would anyone have suggestions as how I can workaround this?
Thank you!
(You should probably use $("form").submit(function() {}) because that also catches when somebody presses Enter in a textfield.)
What you could do is
Don't include the target="_blank" in the form
catch the submission and block it (preferably using event.preventDefault();)
do the ajax call for validation
from within the callback: add the target="_blank" and submit the form again (you could use a check like $("form[target]").length == 1 to see if the form is being submitted for the second time.
While this all can make it work, you should think about validating the form right after the user enters data in each field, this will also improve the user experience a lot.
Use the preventDefault method of the event at the beginning of your click.
$('.submit').click(function(event){
event.preventDefault();
[...]
This will stop your form from submitting and is a better solution than using return false;.
If you need to do a redirect after the ajax call you can do that the standard way:
window.location.replace([url to redirect to]);
Popup blockers block the new window if they are opened in script execution context. If the window is opened through user action then it is allowed. You can try to use jQuery ajax in synchronous mode this will solve your other part of the question because the function will not wait untill ajax response comes and you return true/false conditionally.
$('.submit').click(function(){
$.ajax({
url: "/ajax/save/",
type: "POST",
async: false,
data: { state: $('.state_field').val() },
success: function(data) {
if(data == 'false'){
alert('invalid state');
return false;
}else{
return true;
}
}
);
});

Categories