Preventing Double Submissions
In this page:
$(form).one("submit", handler);
$(form).find(":submit").prop("disabled", true);
Disable After Submit
Disabling the submit button the instant a form is submitted prevents the user from accidentally sending it twice by clicking again before the page responds. This is a simple, direct fix for the classic double-submit bug.
Example: Disable After Submit
<!DOCTYPE html>
<html>
<head>
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
<style>
button { padding:6px 14px; margin:4px; background:#2c6aa0; color:white; border:none; border-radius:4px; cursor:pointer; }
#resetBtn { background:white; color:#2c6aa0; border:1px solid #2c6aa0; }
#output { margin-top:10px; padding:8px; border:1px solid #ccc; border-radius:4px; background:#f7f7f7; font-family:monospace; min-height:24px; }
#demo :where(p, div, span, li, h1, h2, h3, h4, td, th, blockquote, label, section, article, aside) { border:1px solid #4a7fb5; background:#eaf2fb; padding:6px 10px; margin:4px 0; border-radius:4px; }
#demo :where(ul, ol) { border:1px dashed #888; background:#fafafa; padding:8px 8px 8px 32px; margin:6px 0; }
#demo :where(table) { border-collapse:collapse; }
#demo :where(td, th) { border-radius:0; }
#demo :where(input, select, textarea) { margin:4px 0; }
</style>
</head>
<body>
<button id="resetBtn">Reset</button>
<section id="demo">
<form id="myForm"><button id="submitBtn" type="submit">Send</button></form>
</section>
<div id="output"></div>
<script>
var original = $("#demo").html();
function init() {
$("#myForm").on("submit", function() {
$("#submitBtn").prop("disabled", true);
});
}
init();
$("#resetBtn").click(function() {
$("#demo").html(original);
$("#output").empty();
init();
});
</script>
</body>
</html>
Submission Lock
A boolean flag checked at the start of the submit handler can prevent repeated submit handling even if the disable-the-button approach is bypassed somehow, such as by pressing Enter again. The flag is set true on first submit and checked before allowing any further processing.
Example: Submission Lock
<!DOCTYPE html>
<html>
<head>
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
<style>
button { padding:6px 14px; margin:4px; background:#2c6aa0; color:white; border:none; border-radius:4px; cursor:pointer; }
#resetBtn { background:white; color:#2c6aa0; border:1px solid #2c6aa0; }
#output { margin-top:10px; padding:8px; border:1px solid #ccc; border-radius:4px; background:#f7f7f7; font-family:monospace; min-height:24px; }
#demo :where(p, div, span, li, h1, h2, h3, h4, td, th, blockquote, label, section, article, aside) { border:1px solid #4a7fb5; background:#eaf2fb; padding:6px 10px; margin:4px 0; border-radius:4px; }
#demo :where(ul, ol) { border:1px dashed #888; background:#fafafa; padding:8px 8px 8px 32px; margin:6px 0; }
#demo :where(table) { border-collapse:collapse; }
#demo :where(td, th) { border-radius:0; }
#demo :where(input, select, textarea) { margin:4px 0; }
</style>
</head>
<body>
<button id="resetBtn">Reset</button>
<section id="demo">
<form id="myForm"><button type="submit">Send</button></form>
</section>
<div id="output"></div>
<script>
var original = $("#demo").html();
function init() {
let submitted = false;
$("#myForm").on("submit", function(event) {
if (submitted) {
event.preventDefault();
return;
}
submitted = true;
});
}
init();
$("#resetBtn").click(function() {
$("#demo").html(original);
$("#output").empty();
init();
});
</script>
</body>
</html>
Button Feedback
Changing the button's text to something like 'Submitting...' during processing tells users their action was registered and something is happening, rather than leaving them wondering if the click worked. This kind of feedback reduces the temptation to click again.
Example: Button Feedback
<!DOCTYPE html>
<html>
<head>
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
<style>
button { padding:6px 14px; margin:4px; background:#2c6aa0; color:white; border:none; border-radius:4px; cursor:pointer; }
#resetBtn { background:white; color:#2c6aa0; border:1px solid #2c6aa0; }
#output { margin-top:10px; padding:8px; border:1px solid #ccc; border-radius:4px; background:#f7f7f7; font-family:monospace; min-height:24px; }
#demo :where(p, div, span, li, h1, h2, h3, h4, td, th, blockquote, label, section, article, aside) { border:1px solid #4a7fb5; background:#eaf2fb; padding:6px 10px; margin:4px 0; border-radius:4px; }
#demo :where(ul, ol) { border:1px dashed #888; background:#fafafa; padding:8px 8px 8px 32px; margin:6px 0; }
#demo :where(table) { border-collapse:collapse; }
#demo :where(td, th) { border-radius:0; }
#demo :where(input, select, textarea) { margin:4px 0; }
</style>
</head>
<body>
<button id="resetBtn">Reset</button>
<section id="demo">
<form id="myForm"><button id="submitBtn" type="submit">Send</button></form>
</section>
<div id="output"></div>
<script>
var original = $("#demo").html();
function init() {
$("#myForm").on("submit", function() {
$("#submitBtn").text("Submitting...");
});
}
init();
$("#resetBtn").click(function() {
$("#demo").html(original);
$("#output").empty();
init();
});
</script>
</body>
</html>
Async Submission
For AJAX submissions specifically, the button should stay locked until the request actually completes -- success or failure -- since the page never reloads to naturally reset the button's state. Re-enabling it only after the response arrives keeps the protection accurate.
Example: Async Submission
<!DOCTYPE html>
<html>
<head>
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
<style>
button { padding:6px 14px; margin:4px; background:#2c6aa0; color:white; border:none; border-radius:4px; cursor:pointer; }
#resetBtn { background:white; color:#2c6aa0; border:1px solid #2c6aa0; }
#output { margin-top:10px; padding:8px; border:1px solid #ccc; border-radius:4px; background:#f7f7f7; font-family:monospace; min-height:24px; }
#demo :where(p, div, span, li, h1, h2, h3, h4, td, th, blockquote, label, section, article, aside) { border:1px solid #4a7fb5; background:#eaf2fb; padding:6px 10px; margin:4px 0; border-radius:4px; }
#demo :where(ul, ol) { border:1px dashed #888; background:#fafafa; padding:8px 8px 8px 32px; margin:6px 0; }
#demo :where(table) { border-collapse:collapse; }
#demo :where(td, th) { border-radius:0; }
#demo :where(input, select, textarea) { margin:4px 0; }
</style>
</head>
<body>
<button id="resetBtn">Reset</button>
<section id="demo">
<button id="submitBtn">Send</button>
</section>
<div id="output"></div>
<script>
var original = $("#demo").html();
function init() {
$("#submitBtn").on("click", function() {
$(this).prop("disabled", true);
setTimeout(function() {
$("#submitBtn").prop("disabled", false);
}, 1000);
});
}
init();
$("#resetBtn").click(function() {
$("#demo").html(original);
$("#output").empty();
init();
});
</script>
</body>
</html>
Complete Protection
Combining validation, a submission lock, and button feedback covers double-submission from every angle: catching bad input before it's sent, blocking a second submit attempt, and clearly showing the user that processing is underway.
Example: Complete Protection
<!DOCTYPE html>
<html>
<head>
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
<style>
button { padding:6px 14px; margin:4px; background:#2c6aa0; color:white; border:none; border-radius:4px; cursor:pointer; }
#resetBtn { background:white; color:#2c6aa0; border:1px solid #2c6aa0; }
#output { margin-top:10px; padding:8px; border:1px solid #ccc; border-radius:4px; background:#f7f7f7; font-family:monospace; min-height:24px; }
#demo :where(p, div, span, li, h1, h2, h3, h4, td, th, blockquote, label, section, article, aside) { border:1px solid #4a7fb5; background:#eaf2fb; padding:6px 10px; margin:4px 0; border-radius:4px; }
#demo :where(ul, ol) { border:1px dashed #888; background:#fafafa; padding:8px 8px 8px 32px; margin:6px 0; }
#demo :where(table) { border-collapse:collapse; }
#demo :where(td, th) { border-radius:0; }
#demo :where(input, select, textarea) { margin:4px 0; }
</style>
</head>
<body>
<button id="resetBtn">Reset</button>
<section id="demo">
<form id="myForm"><input id="name"><button id="submitBtn" type="submit">Send</button></form>
</section>
<div id="output"></div>
<script>
var original = $("#demo").html();
function init() {
$("#myForm").on("submit", function(event) {
if ($("#name").val().trim() === "") {
event.preventDefault();
return;
}
$("#submitBtn").prop("disabled", true).text("Submitting...");
});
}
init();
$("#resetBtn").click(function() {
$("#demo").html(original);
$("#output").empty();
init();
});
</script>
</body>
</html>
- Disabling the submit button in its
clickhandler instead of the form'ssubmitevent, so pressing Enter can still submit the form twice. - Disabling the button in an AJAX submit and never re-enabling it on error, leaving the form stuck; use the
completecallback or.always(). - Setting a lock flag such as
let sending = falseinside the handler, where it resets on every call, instead of outside it so it persists.
- jQuery handles complex form inputs and reads and changes form state.
- Forms can be changed dynamically as the user interacts.
- Client-side validation and preventing double submissions improve form behavior.
Chapter Quiz — Complete all 5 topics to unlock
0/5 topics done
Complete these topics first: