I have a checkout form on my website that uses a custom validation method implemented with Bootstrap. It has a JavaScript function to prevent the form from being submitted multiple times if it is filled out correctly. I'm using a technique commonly suggested on SO to disable the submission, albeit with vanilla JavaScript instead of JQuery. This is the function:
function submitForm() {
// Fetch all the forms we want to apply custom Bootstrap validation styles to
var forms = document.getElementsByClassName('needs-validation');
// Loop over them and prevent submission
var validation = Array.prototype.filter.call(forms, function(thisForm) {
event.preventDefault();
if (thisForm.checkValidity() === false) {
event.stopPropagation();
}
thisForm.classList.add('was-validated');
<?php if(isset($shipping)){
echo "stripe.createToken(card).then(function(result) {
if (result.error) {
// Inform the user if there was an error
} else {
thisForm.addEventListener('submit', function(event){
event.preventDefault();
return false;
});
// Send the token to the server
console.log('Sending token ' + result.token + '.');
}
});";
}?>
});
};
The form is created like this:
<form id="payment-form" onsubmit="return submitForm()" class="needs-validation" novalidate>
When I test the page with the form filled out correctly, double clicking the submit button prints the "Sending token" message to the console twice when it should only happen once. I thought maybe it was because it was taking too long to get to the part of the function where the form is disabled, but the message prints again no matter how many times the button is clicked.
Using inline event handlers is bad practice and results in poorly factored, hard-to-manage code. Seriously consider attaching your events with JavaScript, instead, eg: https://developer.mozilla.org/en/DOM/element.addEventListener
You're not calling the validation function with the event of when the form was clicked - and then you reference event.preventDefault();, but event is not defined.
Try something like this instead. Remove the onsubmit attribute, and do:
[...document.querySelectorAll('.needs-validation')].forEach((thisForm) => {
thisForm.addEventListener('submit', (event) => { // add the event argument here
event.preventDefault();
if (thisForm.checkValidity() === false) {
// rest of your code
(though, I don't see why you're using .filter in the first place it doesn't make sense here - did you mean to use forEach? And if there's only one #payment-form, couldn't you have selected that by itself?)
To stop a form from submitting you should call event.preventDefault() or return false;
<form onsubmit="handleSubmit"></form>
handlesubmit(event) {
event.preventDefault();
// or return false;
}
I am trying to use parsley to validate a varying number of inputs (order line items) encased within a DIV structure (the main form is for order details).
Due to this I am converting the data outside the form into JSON and injecting into a hidden field.. All works great (including the server side validation).
The issue I am having is that on form submit, the validation runs through, and shows the errors as required, but the form continues through the submission process on 'fail'.
is there any way to see if there are any errors present on the page and prevent the page submit to continue?
Here is what is not working:
$('#submit-form').on('click', function(e){
e.preventDefault();
// Validate line items
$.each($('#lineItems').find('.input-group input'), function(i, val){
$(val).parsley(parsleyConfig).validate();
});
All the errors show up but the page POSTs still.
However, if the data in the main form is no good, on submit it will pop up the validation errors, that is set by this:
// Validation
var parsleyConfig = {
errorsContainer: function(pEle) {
return pEle.$element.parent().siblings('.text-danger');
}
};
$('#editForm').parsley(parsleyConfig);
I have tried using the 'form:submit' event with parsley to no luck either...
$('#editForm').parsley(parsleyConfig).on('form:submit', function(){
// Validate line items
$.each($('#lineItems').find('.input-group input'), function(i, val){
$(val).parsley(parsleyConfig).validate();
});
});
I cannot seem to find a way to get the returned value of if the validation has passed and abort my submit script...
inside your 'form:submit' event listener write this code:
//the validate() calls the error validation and add the error messages:
if ($('#editForm').parsley().validate() == false) {
//Do nothing:
return;
}
I am using jQuery Validator to validate a form and I wanted to disable the fields that were blank when the user clicks submit so that the server does not receive any data from the inputs that were left blank. To disable them, I used the following Javascript:
$(function() {
$("#form1").submit(function() {
$(this).find(":input").filter(function(){ return !this.value; }).attr("disabled", "disabled");
return true; // ensure form still submits
});
});
Here is my problem: This code works great assuming the form was validated on the first submission. However, if the user hits submit but it was not validated, all of the alerts for various required fields and such pop-up, but all of the inputs are disabled. How can I fix this? I need to know how to re-enable them if the form is not validated and properly submitted.
It doesn't make sense to disable the field to submit. Rather—you should first do a front-end only validation that prevents submitting if there are empty fields (and those fields are required to not be empty).
You can set up a variable (or a function) to run through your validation and only submit if it returns true. This is a condensed example of just one input.
var validate = ($('input').val() == '') ? false : true;
if(validate){
// submit your form
} else {
// throw your errors
}
Then it would be good to clear your errors at the beginning of your validation.
Demo - jsfiddle.net/75CqW/
When someone clicks the Submit button, it shows the loading div even if the input is empty.
I don't want the user to see the #loading if he didn't write anything in the input, I've tried to add "required" in the input but the #loading is still showing when the input is empty. What do you think is wrong with my loading div?
Thanks in advance.
Instead of click handler use submit handler for the form - the form validation are triggered on form submit not on submit button click
$(function () {
$("#myform").submit(function () {
$("#controller").hide();
$("#loading").show();
});
});
Demo: Fiddle
Note: You might want to prevent the default action of submit event so that the default form submit is prevented - if you are using ajax to do server side processing
try this
var id = $("#statusid").val();
if (id.length == 0)
{
return false;
}
You need to test for a value (or run a validation check) on the field(s) before firing off the processing code
$(function() {
$(".submit").click(function() {
if $('#statusid').val() {
$("#controller").hide();
$( "#loading" ).show();
}
});
});
I keep getting duplicate entries in my database because of impatient users clicking the submit button multiple times.
I googled and googled and found a few scripts, but none of them seem to be sufficient.
How can I prevent these duplicate entries from occurring using javascript or preferably jQuery?
Thanx in advance!
How about disabling the button on submit? That's what I do. It works fine.
$('form').submit(function(){
$('input[type=submit]', this).attr('disabled', 'disabled');
});
Disclaimer:
This only works when javascript is enabled on the user's browser. If the data that's being submitted is critical (like a credit card purchase), then consider my solution as only the first line of defense. For many use cases though, disabling the submit button will provide enough prevention.
I would implement this javascript-only solution first. Then track how many duplicate records are still getting created. If it's zero (or low enough to not care), then you're done. If it's too high for you, then implement a back-end database check for an existing record.
This should do the trick:
$("form").submit(function() {
$(":submit", this).attr("disabled", "disabled");
});
No JQuery?
Alternatively, you can make a check from db to check if a record already exist and if so, don't insert new one.
One technique I've seen used is to assign a unique ID to every form that's opened, and only accept one submission per form based on the ID.
It also means you can check how many times people aren't bothering to submit at all, and you can check if the submission genuinely came from your form by checking if it's got an ID that your server created.
I know you asked for a javascript solution, but personally I'd do both if I needed the robustness.
Preventing the double posting is not so simple as disabling the submit button. There are other elements that may submit it:
button elements
img elements
javascripts
pressing 'enter' while on some text field
Using jQuery data container would be my choice. Here's an example:
$('#someForm').submit(function(){
$this = $(this);
/** prevent double posting */
if ($this.data().isSubmitted) {
return false;
}
/** do some processing */
/** mark the form as processed, so we will not process it again */
$this.data().isSubmitted = true;
return true;
});
Here is bit of jQuery that I use to avoid the double click problem. It will only allow one click of the submit button.
$(document).ready(function() {
$("#submit").on('click', function() {
});
});
I'm not sure what language/framework you're working with or if it's just straight HTML. But in a Rails app I wrote I pass a data attribute on the form button disable_with which keeps the button from being clickable more than once while the transaction is in process.
Here's what the ERB looks like.
<%= f.button "Log In", class: 'btn btn-large btn-block btn-primary', data: {disable_with: "<i class='icon-spinner'></i>Logging In..."} %>
This is what I came up with in https://github.com/liberapay/liberapay.com/pull/875:
$('form').on('submit', function (e) {
var $form = $(this);
// Check that the form hasn't already been submitted
if ($form.data('js-submit-disable')) {
e.preventDefault();
return false;
}
// Prevent submitting again
$form.data('js-submit-disable', true);
// Set a timer to disable inputs for visual feedback
var $inputs = $form.find(':not(:disabled)');
setTimeout(function () { $inputs.prop('disabled', true); }, 100);
// Unlock if the user comes back to the page
$(window).on('focus pageshow', function () {
$form.data('js-submit-disable', false);
$inputs.prop('disabled', false);
});
});
The problem with the method described here is that if you're using a javascript validation framework and the validation fails, you won't be able to correct and re-submit the form without refreshing the page.
To solve this, you need to plug into the success event of your validation framework and only then, set the submit control to disabled. With Parsley, you can plug into the form validated event with the following code:
$.listen('parsley:form:validated', function(e){
if (e.validationResult) {
/* Validation has passed, prevent double form submissions */
$('button[type=submit]').attr('disabled', 'disabled');
}
});
If you are using client-side validation and want to allow additional submit attempts if the data is invalid, you can disallow submits only when the form content is unchanged:
var submittedFormContent = null;
$('#myForm').submit(function (e) {
var newFormContent = $(this).serialize();
if (submittedFormContent === newFormContent)
e.preventDefault(true);
else
submittedFormContent = newFormContent;
});
Found at How to prevent form resubmission when page is refreshed (F5 / CTRL+R) and solves the problem:
<script>
if ( window.history.replaceState ) {
window.history.replaceState( null, null, window.location.href );
}
</script>
That is what I did to solve the problem.
I disabled the button for a second with adding setTimeout twice:
- the 1st time is to let the JS form fields verification work;
- the 2nd time is to enable the button in case if you have any verification on your back end, that may return an error, and hence the user will want to try to submit the form again after editing his data.
$(document).ready(function(){
$('button[type=submit]').on("click", function(){
setTimeout(function () {
$('button[type=submit]').prop('disabled', true);
}, 0);
setTimeout(function () {
$('button[type=submit]').prop('disabled', false);
}, 1000);
});
});