jQuery submit form AFTER validating it with ajax - javascript

I have a form with one tricky field that needs to pass validation on the server side. So i need to capture for submit, send ajax request with this field, get result, if result is valid the continue form submission, other wise stop submission and show message.
How would i do that?
I got lost a little bit in "big picture" with events and callbacks.
Here is what i have so far.
$("form").submit(function( event ) {
event.preventDefault();
return check();
});
function check() {
var field = $('#myFiled').val();
if (!field ) {
show.error('Please enter VIN number and try again.');
return false;
}
$.getJSON('MyURL', function(data){
if (!data.valid) show.error('Invalid entry! Please try again.');
})
}
UPDATE
Please read the question.
In case of successful validation i need to continue regular form submission. Not via AJAX.

$("form").submit(function( event ) {
event.preventDefault();
checkAndSubmit();
});
function checkAndSubmit() {
var field = $('#myFiled').val();
if (!field ) {
show.error('Please enter VIN number and try again.');
}
else {
$.getJSON('MyURL', function(data){
if (!data.valid) {
show.error('Invalid entry! Please try again.');
}
else {
$.post('yourFromPostURL', $('form').serialize(), function(data){
//show something of success or failure.
});
}
})
}
}

Judging by your check() function, you already understand basic JavaScript validation. If you want a form's validation to fail, have its .submit() method return false, otherwise return true.
Just treat the data returned by the AJAX request the same way you did the field variable.
Perhaps the one thing your missing is how to make check() return false from inside the getJSON function. The answer to that is a simple matter of variable scope.
var data;
$.getJSON('MyURL', function(data_){
data = data_;
});
if (!data.result) return false;
Since JavaScript has function scope, data will still be accessible inside of .getJSON().
There is one more thing though, .getJSON() is an asynchronous AJAX request, meaning your validation function will finish without waiting for the result of the request. You want to use a syncrhonous ajax request so your check() function won't finish until your validation is done. However there is no way to make .getJSON() synchronous so you will have to use the .ajax() method. See this post.
EDIT:
Your issue is if there are no validation errors, you do not return a value. You must return true;.

The alternative to the AJAX form submit is to prevent form submission and execute validation at the button level.
$('#submitButtonID').click(function (e) {
e.preventDefault();
//start your AJAX validation
checkAndSubmit();
}
Then validate and upon success, you can still submit the form regularly.
function checkAndSubmit() {
var field = $('#myField').val();
if (!field ) {
show.error('Please enter VIN number and try again.');
}
else {
$.getJSON('MyURL', function(data){
if (!data.valid) {
show.error('Invalid entry! Please try again.');
}
else {
$('form').submit();
}
});
}
}
Server side validations will run upon post, but you won't interrupt the form submission with your AJAX validation because it's only captured at the button level. (If you need to capture the Enter button, see this answer: Capturing Enter button to submit form

Related

Wait for form.submit() / POST to complete

I'm stuck in a really bizarre situation here. It's complicated to explain but I'll try my best.
Detailed explanation of the issue:
On every top Nav click (Green donuts/circles), or next button, I must submit the form, if it exists and is valid. If not valid, form.valid() triggers validation errors and return false would stop any further propagation. This setup was working flawlessly until I noticed a strange behavior which isn't very persistence. Form on my 3rd tab, specifically, is quite data heavy. When I hit next button it should practically go thru the same process: check for an existing form, if valid, then submit. Submit calls the POST action method and when post completes it GETs the view for next tab. It works like this 5/10 times but at other times GET executes before the POST, which causes next page to load with incomplete data. When I put breakpoints to debug, I see GET for the next tab executing before POST of the current tab.
UI Explained:
I have a UI with 4 navigation <a> buttons on top - in the center there's a always a form - and at the bottom I have Previous & Next buttons.
Forms are constructed in MVC using Ajax.BeginForm
For each Nav link <a> element on top, I have a JavaScript function
var LoadTabs = function (e, arg) {
// This is to validate a form if one of the top links is clicked and form has incomplete fields...
if (arg !== "prev" && arg !== "next") {
if (!window.ValidateForm(false)) return false;
}
var url = $(this).attr('data'); // this contains link to a GET action method
if (typeof url != "undefined") {
$.ajax(url, { context: { param: arg } }).done(function (data) {
$('#partialViewContainer').html(data);
});
}
}
This function above binds to each top link on page load.
$('.navLinks').on('click', LoadTabs);
My Next & Previous buttons basically trigger the click event i.e. LoadTabs function.
$('button').on('click', function () {
if (this.id === "btnMoveToNextTab") {
if (!window.ValidateForm(true)) return false;
$.ajax({
url: url,
context: { param: 'next' },
method: "GET",
data: data,
success: function(response) {
if (typeof response == 'object') {
if (response.moveAhead) {
MoveNext();
}
} else {
$('#mainView').html(response);
}
ScrollUp(0);
}
});
}
if (this.id === "btnMoveToPreviousTab") {
MoveBack();
}
return false;
});
MoveNext() Implementation is as below:
function MoveNext() {
var listItem = $('#progressbarInd > .active').next('li');
listItem.find('.navLink').trigger('click', ['next']);
ScrollUp(0);
}
The problem is, for some reasons, when Nav Link 3 is active and I hit NEXT button - Instead of posting the form first via form.submit() - the nav 4 gets triggered - hence GET for nav 4 runs before form POST of nav 3.
My ValidateForm method is basically just checking if the form exists and is valid then Submit, else returns false. Its as below:
function ValidateForm(submit) {
var form = $('form');
// if form doesn't exist on the page - return true and continue
if (typeof form[0] === "undefined") return true;
// now check for any validation errors
if (submit) {
if (!$(form).valid()) {
return false;
} else {
$(form).submit();
}
}
else {
return true;
}
return true;
}
My speculation is that form.submit does get triggered as it should be but since submit takes a little longer to finish it continues with the next code block in the button onclick event.
I first thought that this is a server side issue as in the POST I'm saving a big chunk of data with a few loops, and any code block that's process heavy I have that part in
var saveTask = Task.Factory.StartNew(() => ControllerHelper.SomeMethod(db, model)); Task.WaitAll(saveTask);
WaitAll will wait and pause the execution until SomeMethod finishes executing. I'm not sure how can I lock a process in JavaScript and wait for it to finish execution. Because I think If i can somehow lock the form.submit() in ValidateForm until its finished processing .. via a callback method perhaps...
Please if anyone can put me in right direction, I'd greatly appreciate the help. If you need more information please let me know I'd be happy to provide!
Ajax is async, and your forms submit which is using Ajax.BeginForm() is using ajax. What is happening is that when you click your 'Next' button, which triggers the $('button').on('click', function () { code:
You call the ValidateForm() function (and assuming its valid),
your $(form).submit(); line of code starts making a ajax POST
The code progresses to the final return true; line while the ajax
call is executing.
Because the ValidateForm() function returned true, the $.ajax
GET call now starts, but at that point the ajax POST in the
ValidateForm() function may not have finished executing causing
your GET method to return invalid data
You need to change your code so that the GET call is made once the POST method call has completed. And since your using the $.ajax() methods throughout your code, and $.ajax() gives you more flexibility, it seems unnecessary to use Ajax.BeginForm() (and the extra overhead of including the jquery.unbtrusive-ajax.js script). You should also be handling the forms .submit() function (if you do not want the 'Next' button to be a submit button in the form, you could just trigger the .submit() event in the buttons .click() handler)
$(document).on('submit', 'form', function(e) {
e.preventDefault(); // cancel default submit
var form = $(this);
if (!form.valid()) {
return; // will display the validation errors
}
.... // get the relevant urls to the GET and POST methods etc
$.post(postUrl, form.serialize(), function(data) {
.... // not clear if your [HttpPost] method returns anything
}).done(function() {
$.get(getUrl, someData, function(response) {
.... // Update the DOM with the next form?
.... // Re-parse the validator for client side validation
}
}).fail(function() {
.... // code that you might run if the code in the [HttpPost] method fails
});
});
You should also consider returning the appropriate 'next' view in the [HttpPost] method so that you don't then needs to make a second call back to the server to get it.
It is also worth reading the Deferred Object documentation and the use of $.when(), $.then() etc.

setTimeOut AFTER jQuery form submit

Here is the deal: I have a form, that takes quite some time to submit, because I'm waiting for some third party web services. So what I'm trying to achieve is, that after the submit button is clicked, it gets disabled, is assigned a special class and if it takes more than 5 seconds to submit the form, a notice is displayed.
I've came up with this:
$('#register_index_button').click(function(){
$(this).addClass('bt_button_loader');
$(this).val('Please wait');
$(this).attr('disabled', 'disabled');
$('#register_index_form').submit();
//it takes more than 5 seconds, display notice
setTimeout(function() {
$('#notice').html('Still waiting ...');
}, 5000);
});
Everything works fine, except the timeout function. I guess after I submit the form with jQuery, everything else after that is ignored?
Thank you for your help!
Try attaching an event handler on the form for the "submit" event. Put the timeout event handler function.
(https://developer.mozilla.org/en-US/docs/Web/Events/submit)
$('#register_index_form').on('submit', function(){
setTimeout(function() {
$('#notice').html('Still waiting ...');
}, 5000);
});
You should submit after your services get returned, I really don't see any code there that does that, and after you receive your service response, you submit your form.
$('#register_index_button').click(function(){
$(this).addClass('bt_button_loader');
$(this).val('Please wait');
$(this).attr('disabled', 'disabled');
//it takes more than 5 seconds, display notice
setTimeout(function() {
$('#notice').html('Still waiting ...');
}, 5000);
});
Place it when the service is retrieved, an ajax call, in complete method.
$('#register_index_form').submit();
As #gaemaf stated.
$('#register_index_button').click(function(){
$(this).addClass('bt_button_loader');
$(this).val('Please wait');
$(this).attr('disabled', 'disabled');
$('#register_index_form').submit(
//Nested inside of the submit to be executed when submit
setTimeout(function() {
$('#notice').html('Still waiting ...');
}, 5000);
);
});
Another method would be to gather up all of the fields from the form and submit them using an Ajax submit.
That way you can create the 'Please wait' when the ajax is fired and have a confirmation that the form has been received and is being processed. So something like....
$('#register_index_form').submit(function(){
var url = "path/to/your/script.php";
// the script where you handle the form input.
$.ajax({
type: "POST",
url: url,
data: $("#register_index_form").serialize(),
// Gets the forms elements and submits them
timeout: 10000
// How long the Ajax will wait before considering the call to have failed
})
.done(function( data ) {
//Do something ...
});
return false; // avoid to execute the actual submit of the form.
});

form.submit returning false still Page Redraws

$('#GramForm').submit(function () {
// Ajax Save New Style If Available.
SaveNewStyle() // this function also return false.
return false;
});
This is my code. But the problem is when form is submitted it redraw whole page.
What could be the possible reason for this problem?
Thanks for you help in advance.
Regards.
You can use preventDefault to stop the form submission.
$('#GramForm').submit(function (e) {
e.preventDefault(); //stop the form submission
// Ajax Save New Style If Available.
SaveNewStyle() // this function also return false.
return false;
});
The reason why the return false is failing is you must have a JS error in the SaveNewStyle which is not allowing the return false to run. See my comment above on preserving the log so you can see the error.

Stuck in infinite loop while trying to intercept form submission

I am writing Javascript/JQuery code, where I want to intercept the form submission before submitting it because I need to check if the fields are valid.
So I block the default event from happening, check what I want to, then fire the event again if everything is ok. Problem is, this triggers the exact same function and I get stuck in an infinite loop.
Is there a way around this? I can think of work arounds, but they are, after all, work arounds and not the most elegant of solutions.
Here is my code:
$("#register_form").submit(function(event) {
event.preventDefault();
console.log('form submit attempt');
checkUsername();
$("#register_form").submit();
});
In order to be able to stop the form submitting if there are errors, you need to return false from the function. You'll need to make sure that the checkUsername() function returns bool.
Try this...
$("#register_form").submit(function(event) {
if(checkUsername())
return true;
return false;
});
Or even better...
$("#register_form").submit(function(event) {
return checkUsername();
});

onunload is not working without a call to function alert?

Lets say I'm trying to do the following:
window.onunload = handleOnClose;
function handleOnClose()
{
logout();
// alert('You have been signed out.');
}
It goes into the handleOnClose if I use the alert function. I don't want to alert any messages on unload. But it doesn't seem to go in the handleOnClose function at all if I remove the alert function.
Add return ""; maybe ?:
window.attachEvent( "onunload", function(event) {
this_function_works(); // must be synchronous
event.preventDefault ? event.preventDefault() : event.returnValue = false;
});
And make sure logout() is executing before page closes. Meaning, you are not trying to do AJAX calls here, or submit forms. You can set or clean cookies or localStorage.

Categories