Javascript preventing submit based on ajax response - javascript

I can't figure out why this code will not prevent a submit. All html is linked properly. All alerts display as expected. It doesn't seem as though I am losing scope on the event. Any suggestions, fixes or explanations would be awesome!
//Alert the potential customer if the email entered already exists.
function emailUniqueness() {
// When the Submit Button is clicked, then execute the following function...
$('#form').submit(function(event) {
//Remove error messages if they exist
$("#emailNotUniqueErr").empty();
$("#emailNotUniqueErr").removeClass('alert alert-warning');
//Make the call to servlet method
$.ajax({
url: 'http://localhost:8080/ShoppingCart/ajax.do',
success: function(response) {
searchForEmail(response, event);
}
});
//event.preventDefault(); works when placed here but is pointless.
});
}
function searchForEmail(response, event) {
//alert returns type "submit"
alert(event.type);
var emailEntry = $("#email").val();
var emailExists = false;
$.each(response, function(index, item) {
if(emailEntry == item.email) {
//Set to true when a match is found
emailExists = true;
//Exit the .each loop
return false;
}
});
//alert returns appropriate true or false for input entry
alert(emailExists);
if(emailExists) {
//still is type submit
alert(event.type);
//Properly print the warning if email exists
$("#emailNotUniqueErr").addClass('alert alert-warning col-sm-offset-2');
$('×').appendTo("#emailNotUniqueErr");
$('<strong>Warning! Account already exists. One account per Email.</strong>').appendTo("#emailNotUniqueErr");
//does not prevent submit???
event.preventDefault();
} else {
//No match found allow submit, remove errors
$("#emailNotUniqueErr").empty();
$("#emailNotUniqueErr").removeClass('alert alert-warning');
return true;
}
}

ajax call is asynchronous. Therefore the line searchForEmail(response, event); is executed with some delay (when the response comes for the request). When it is executed the form is already submitted. The order of execution is given below.
Function emailUniqueness() is called and execution of the function starts
ajax request is sent scheduling the callback to be executed after the response comes
Function emailUniqueness() function execution ends
Form submission
Response for the ajax request comes, callback executed, searchForEmail(response, event); is called
event.preventDefault() is called (this is called after the form is submitted)
You have to call the method event.preventDefault(); inside emailUniqueness() function which changes the order to the following.
Function emailUniqueness() is called and execution of the function starts
ajax request is sent scheduling the callback to be executed after the response comes
event.preventDefault() is called (this prevents form submission)
Function emailUniqueness() function execution ends
Response for the ajax request comes, callback executed, searchForEmail(response, event) is called
As a solution,
prevent the form submission inside emailUniqueness function
submit the form with $('#form').submit() inside searchForEmail function.

Related

Form not submitting even no errors and OK response

I'm stuck with returning.
I need that if response is "ok", my form would be submitted else document wouldn't reload.
I've tried like that:
$(window).load(function(){
$('.check-connection').click(function(){
u = {};
u["host"] = $('[name="host"]').val();
u["db_user"] = $('[name="db_user"]').val();
u["db_pass"] = $('[name="db_pass"]').val();
u["db_name"] = $('[name="db_name"]').val();
$.post('check-connection.php',{secure:true,data:u}).done(function(r){
if(r == "ok"){
/*
here problems even returns ok
alert(r); - gives answer ok if trying to check..
*/
return true;
} else {
alert(r);
return false;
}
});
return false;
});
});
Any ideas? offers?
Probably you might want to remove the last return false; because it is returning before the ajax completes.
Let it return when the .done() handler is executed.
You can not return a boolean from within the ajax done function and expect it to be passed back to the click handler. The ajax is asynchronous and so the click handler will complete execution before the ajax response is received.
The logic should be: call the ajax on a button click (not form submit), then submit the form from within the ajax success handler, else don't do anything.

Wait asynchronous .ajaxComplete() before form submitting

I need to override form's submit method to wait until the ajax request will be completed. At the same time, ajax request should be asynchronous to display a progress indicator, also default form handler must be continued after response receiving.
I can't use event.preventDefault() and then manual call form.submit() for this, because form sending results should be opened in the new tab of the browser. If form.submit() will be called from the code, then some browsers (i.e. chrome) will block the new tab/window.
Pseudocode for clarity:
$('#form').submit(function(e) {
var result;
startIndicator();
asyncAjaxCheckResults(); // ajax complete handler changed 'result' var
stopIndicator(); // stopping indicator after async ajax will be completed
// continue with default submit behavior if we received desired result
// else prevent executing
if (result !== 'desired result') {
e.preventDefault();
}
});
Can anything be done in this case? Maybe $.deferred can help or infinity loop?
I think you need a sync ajax call, so the script will wait for the respons and then continue running.
$.ajax({
...
async:false,
...
});
http://api.jquery.com/jQuery.ajax/
another way is to add click event to the submit button instead submit event to the form,
send the ajax and use event.prevenrDefault, on ajax success callback fire the form submit - $('#form').submit().

Trying to validate results after doing an ajax call

Alright so i have form validation function.the function runs through form validation functions that returns false if the field isn't valid.
The problem is when it get to the function that uses ajax to check if the field is valid.
for some reason its seems that it doesn't "wait" for ajax to return and returns false automatically.
is there a way around this?
Here is the code:
function form_validation(){
if (!NewValidationForm('pcode', 'Please fill in all the fields'))
return false;
if (!NewValidationForm('fname', 'Please fill in all the fields'))
return false;
if(!validate_coupon()){
alert("bad!!");
return false;
}
return true;
}
function validate_coupon(){
var url = $j("#site_url").val() + 'ajax_functions.php';
var coupon = $j("#pcode").val();
var result_status = false; // seem its jumps from here to:
$j.ajax({
type: "POST",
url: url,
data: { ajax: 'ajax', coupon: coupon}
}).success(function(insertID){
var obj = $j.parseJSON(insertID);
if(obj.status == 1){
result_status = true;
}
});
// straight over here
if(result_status == true){
return true;
}
}
Usually in this situation I do something like this in $(document).ready():
$('form').submit(function (evt) {
if (!$(this).attr('data-submitted')) {
evt.preventDefault();
$(this).attr('data-submitted', 'true');
// call your form validation code here that fires the ajax request
return false;
}
return true;
});
Then, in your $.ajax callback, when your validation completes, call $('form').submit(). This effectively uses an attribute on the form as a flag for whether the state of the validation request. When the user first submits the form, the flag gets set and the validation process begins. When the validation completes, the form's submit event is triggered, and since the flag is set, this time the form gets submitted like normal.
If this approach works for you, you'll probably want to add a little polish. For example, you'll probably want to disable the submit button before calling $.ajax and enable it again if the validation fails. You'll also probably want to remove the data-submitted attribute from the form if the validation fails, since the user might submit the form a second time and you presumably want to perform another validation in that case.

jQuery: Submit a form only if no AJAX is currently running on the page

When the city input field is blurred I get somnething via an ajax request and set that as the value of a hidden field in the same form that the city field resides in.
$('input#city').on('blur', function() {
$.ajax({
url: 'get/something?param=val',
success: function(response) {
$('input:hidden[name="something"]').val(response);
}
});
});
If the user submits the form immediately after blurring off the city field sometimes due to latency the hidden field is not populated because the SQL on the other end is taking too long.
The form that both these fields are in is also submitted via ajax:
$('form#find-users').on('submit', function() {
if(NO_AJAX_CURRENTLY_RUNNING_ON_PAGE) {
// do stuff
}
});
How to detect if no ajax is running on the page? This will ensure that the city ajax was completed and the hidden field populated before the form is processed.
EDIT
Actually it won't, it will only prevent the form from being submitted. But if I can detect that then I can use a setInterval and keep trying to run that code until it runs because ajax is complete. Ideally there will be something in jQuery that waits until other ajax is complete and then submits.
Use jQuery's Ajax Events. As long as all of your Ajax calls are generated using jQuery, you have a way of knowing if any Ajax calls are outstanding.
$(document).ready(function() {
var ajaxBusy = false;
$(document).ajaxStart( function() {
ajaxBusy = true;
}).ajaxStop( function() {
ajaxBusy = false;
});
});
Edit:
So that answers your direct question about "How do I know if there is any Ajax call running."
Alternatively, you could disable the form's submit buttons when run your blur handler, and then re-enable it when you're done.
$('input#city').on('blur', function() {
var submit = $(this).closest('form').find(':submit:enabled');
submit.prop('disabled', true);
$.ajax('get/something?param=val').done(function(response) {
$('input:hidden[name="something"]').val(response);
}).always(function() {
submit.prop('disabled', false);
});
});
Edit 2:
So now we're at the point where we would like to delay the form submission until all current Ajax calls have completed. We let people click on the submit button, but if there are pending Ajax calls we don't do anything right away.
We can use a Deferred object to help us with this.
$(document).ready(function() {
var ajaxDefer = $.Deferred().resolve();
$(document).ajaxStart( function() {
ajaxDefer = $.Deferred();
}).ajaxStop( function() {
ajaxDefer.resolve();
});
$('form#find-users').on('submit', function() {
ajaxDefer.always(function() {
// Code here will always be executed as soon as there are no
// Ajax calls running.
// this points to the deferred object (ajaxDefer), so use the closure
// to carry over any variables you need.
});
});
});
When we're just starting out, we set up our ajaxDefer object in a resolved state. That means any functions attached using .always() will execute immediately.
When the first Ajax call starts, we replace the old ajaxDefer object with a new one that has not been resolved. Any new functions attached using ajaxDefer.always() will be deferred until later.
When the last Ajax call completes, we call ajaxDefer.resolve(), which causes any unexecuted deferred functions to execute. Now we're back to our initial state, where any newly-attached functions will execute immediately.
When somebody tries to submit the form, create an anonymous function that does the work and attach it to ajaxDefer. It will get executed when appropriate, depending on if there are any outstanding Ajax requests or not. Be mindful of your closures.
Use this to check if AJAX calls are currently in-progress using JQuery:
if ($.active == 0) {
...
}
you can put a variable in the global namespace, perhaps named ajaxLock and toggle it on when AJAX starts and off when the response comes. Then check it before allowing submit.
something like
var ajaxLock = 1;
$('input#city').on('blur', function() {
$.ajax({
url: 'get/something?param=val',
success: function(response) {
$('input:hidden[name="something"]').val(response);
ajaxLock = 0;
}
});
});
Use a lock variable like you suggested:
$('input#city').on('blur', function() {
window.AJAX_CURRENTLY_RUNNING_ON_PAGE = true;
$.ajax({
url: 'get/something?param=val',
success: function(response) {
$('input:hidden[name="something"]').val(response);
},
complete: function() { window.AJAX_CURRENTLY_RUNNING_ON_PAGE = false; }
});
});
$('form#find-users').on('submit', function() {
if(window.AJAX_CURRENTLY_RUNNING_ON_PAGE) {
return;
}
//dostuff
});
What i could have done on this circumstances is to use plugin like block ui or disable the form submit button,the reason is you need to be interactive in your design,you may well able to lock the form submission,but its better to give a message or have a modal gray out

How do I control form submission from within ajax callback?

I originally had the return true/false in my ajax callback, and realized it's probably not in the right context to be called, so I rewrote my function as follows, but it is still not working. Is the submit variable not carrying through from the callback function either? The confirmation (if .btn-danger) is working, but not just if you hit submit and confirmation is not needed)
$('#form').submit(function(e){
var submit = false;
if($('.btn-danger').length){
submit = true;
} else {
$.ajax({
url: base_path+"ajax/myajaxfile",
type: "post",
data: {
data1 : $("#amount").val(),
data2 : $("option:selected").val()
},
dataType: "json",
success: function(data) {
if (data.needconfirmation === 'true'){
$('#edit-submit').val("Confirm");
$('#edit-submit').removeClass("btn-primary");
$('#edit-submit').addClass("btn-danger");
$('#payment-form').after('<span class="warning"> Do you really wanna?</span>');
} else {
submit = true;
}
},
error: function(data) {
alert("an error has occurred");
}
});
}
if (submit){
return true;
} else {
return false;
}
});
I think your issue is that ajax calls are asynchronous by default - so the return value of the function is being evaluated before the success function is ever called, and therefore the submit variable is still false.
You need to either make the ajax call synchronous:
async: false
or probably better would be to restructure it.
One of the most confusing aspects of doing AJAX for the first time is Asynchronous part. With normal Javascript (well, normal jQuery at least), you handle a submit like so:
$('#form').submit(function(e){
var submit = /*Figure out if it was a success or not*/;
if (submit){
return true;
} else {
return false;
}
});
An event triggers a submission, you figure out whether or not it's valid, and then you either proceed or you don't.
With an AJAX submission though that "Figure out if it was a success" step happens outside the normal flow of things. This means that what you want to do is ALWAYS return false; you don't know whether to proceed yet, so don't proceed. Your AJAX callback (the "success:" function in your AJAX call's options) is whether the "figure out" code goes, and your's currently has the right idea with "success = true" ... except that by the time it resolves, your original submit function will already be over (you'll have returned false to it).
So, what you then need to do is modify your success handler to do ... whatever it is that normally would happen when you submit. This might be as simple as form.submit() of a hidden form, or it might be more complex; I don't know your app. Hopefully this gives you the basic idea though.
$.ajax is asynchronous, so the rest of your code continues on before the success callback happens, so it setting submit = true doesn't affect the check at the end of your function.
The confirmation (if .btn-danger) is working, but not just if you hit submit and confirmation is not needed
How do you know if confirmation is needed or not? You may want to add a check for that where you check for .btn-danger.
Also, you can clean up the last bit of your code by just doing
return submit;

Categories

Resources