Reputation: 340
Currently having some issues with jQuery Form Submissions in my project.
My project contains a general jQuery Code which prevents form double submissions (e.g. someone clicks the 'submit' button multiple times).
//prevent multiple form submissions
jQuery.fn.preventDoubleSubmission = function () {
$(document).on('submit', this, function (e) {
let $form = $(this);
if ($form.data('submitted') === true) {
e.preventDefault();
} else {
$form.data('submitted', true);
}
});
return this;
};
$(function () {
$('form').preventDoubleSubmission();
});
This code is included into every single page - so every form should be 'protected'.
For some specific forms I need to check some values before they are submitted - and show a confirm box, if some values are missing (e.g. Are you sure you want to submit this form without value X?)
Here's the code:
$(document).on('submit', 'form[name="article"]', function (e) {
e.preventDefault();
let form = this;
let $form = $(form);
let $category = $form.find('select#article_category'); //get category
if ($category.length && !$category.val()) { //check if category is selected
$.confirm({ //jquery confirm plugin
title: "Are you sure?",
content: "Value X is missing - continue?",
buttons: {
confirm: {
action: function () {
$form.off('submit');
form.submit();
}
}
}
});
} else {
$form.off('submit');
form.submit();
}
});
So basically, if the user tries to submit the form, but the value X is missing, there will be a Yes/No Popup first - if the value exists, the form will be submitted right away.
Problem:
When I want to submit the form, I call $form.off('submit');
to remove the event handler and submit afterwards with form.submit();
. Sadly this also removes my preventDoubleSubmission event handler, which allows double submissions again.
Is there a way to fix my issue? Thanks
Upvotes: 3
Views: 3911
Reputation: 340
So I finally figured out a relatively ok solution for me. However it is very simple and I might stick with it.
//form submission function
function submitForm(form) {
let $form = $(form);
let $submit = $form.find('button[type=submit]'); //find submit button
$submit.attr('disabled', true); //disable button = prevent double submission
form.submit(); //submit form
}
//submission for every form but not .form-confirm
$(document).on('submit', 'form:not(.form-confirm)', function (e) {
e.preventDefault();
submitForm(this); //call function
});
$(document).on('submit', 'form[name="article"]', function (e) {
e.preventDefault();
let form = this;
let $form = $(form);
let $category = $form.find('select#article_category'); //get category
if ($category.length && !$category.val()) { //check if category is selected
$.confirm({
title: "Are you sure?",
content: "Value X is missing - continue?",
buttons: {
confirm: {
action: function () {
submitForm(form); //call function
}
}
}
});
} else {
submitForm(form); //call function
}
});
So how does it work?
Basically I just disable the submit button after submitting (=prevent double submissions). I added a class called form-confirm
to the specific form which the popup should show, so the general rule does not work there.
I always use preventDefault
and use form.submit()
to submit right away in my code.
Upvotes: 1
Reputation: 397
Below is a code snippet with a correct solution. There were multiple issues with your original approach, highlighted below the snippet. Better to run this snippet in a different code playground, where action with javascript work, e.g. JSFiddle.
//prevent multiple form submissions
function submitOnce (e, $form) {
alert('submitted = ' + $form.data('submitted'));
if ($form.data('submitted') === true) {
e.preventDefault();
alert('Double-submission prevented!');
} else {
$form.data('submitted', true);
alert('Double-submission param saved');
}
}
$(document).on('submit', 'form[name="article"]', function (e) {
let form = this;
let $form = $(form);
let $category = $form.find('select#article_category'); //get category
if ($category.length && !$category.val()) { //check if category is selected
if ( confirm("Are you sure?") ){
submitOnce(e,$form);
}
else {
e.preventDefault();
}
} else {
submitOnce(e,$form);
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form name="article" action="javascript:alert('Form submitted!');">
<select id="article_category" name="select1">
<option></option>
<option>option1</option>
<option>option2</option>
</select>
<input type="submit" />
</form>
edit: adding explanations
$form.off()
would work if you would bind 'submit' event handler directly on the form element, but in both cases handlers are registered on the document.
Calling form.submit()
is not necessary, since we are already in a submit handler, hence submit already called. We just need to prevent submissions to continue.
Better is to have just one submit handler, and deal with double submits there.
e.preventDefault();
has to be just in the else clause for a non-confirmed case and in submitOnce()
. You had it at the beginning of the main handler, but it was useless there, since form.submit()
was called again inside, and this call does not prevent the default.
My approach is not bullet-proof and serves just as a demonstration of what needed to be changed.
Upvotes: 2
Reputation: 11437
One approach is to use a normal span with a click event. Once it is clicked you can disable it (using a class for example) and then submit form. This approach allows you to control form submission without the need of extra coding.
See this example:
$submitBtn = jQuery(".submit");
$form = jQuery("form[name='article']");
$submitBtn.on("click", function() {
if (jQuery(this).hasClass("disabled"))
return;
let $category = $form.find('.name'); //get value
if ($category.length && !$category.val()) { //check if value is set
$.confirm({ //jquery confirm plugin
title: "Are you sure ?",
content: 'Value x is missing - continue ?',
buttons: {
confirm: {
action: function() {
$form.submit();
$submitBtn.addClass("disabled");
}
},
cancel: function() {
//$.alert('canceled');
}
}
});
return;
}
$submitBtn.addClass("disabled");
$form.submit();
});
form {
border: 1px solid rgba(0, 0, 0, 0.1);
padding: 1.5rem;
display: flex;
flex-direction: column;
width: 200px;
}
form input {
margin-bottom: 0.5rem;
padding: 0.3rem;
border-radius: 3px;
border: 1px solid gray;
}
form .submit {
padding: 0.3rem 1rem;
cursor: pointer;
border-radius: 3px;
background-color: rgba(0, 0, 0, 0.1);
text-align: center;
transition: all 0.3s;
}
form .submit.disabled {
opacity: 0.5;
cursor: default;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/jquery-confirm/3.3.2/jquery-confirm.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-confirm/3.3.4/jquery-confirm.min.js"></script>
<form action="" name='article'>
First name:<br>
<input type="text" name="firstname" value="My First Name" class='name'>
<br> Last name:<br>
<input type="text" name="lastname" value="My Last Name">
<br><br>
<span class='submit'>Submit</span>
</form>
Upvotes: 1