jQuery:表单提交 - 多个事件处理程序
jQuery: Form Submission - Multiple Event Handlers
目前我的项目中 jQuery 表单提交有一些问题。
我的项目包含一个通用的 jQuery 代码,可以防止表单重复提交(例如,有人多次单击 'submit' 按钮)。
//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();
});
此代码包含在每个页面中 - 因此每个表单都应 'protected'。
对于某些特定的表单,我需要在提交之前检查一些值 - 如果缺少某些值,则显示确认框(例如,您确定要提交没有值 X 的表单吗?)
代码如下:
$(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();
}
});
所以基本上,如果用户尝试提交表单,但缺少值 X,则会首先出现一个 Yes/No 弹出窗口 - 如果该值存在,将立即提交表单。
问题:
当我想提交表单时,我调用 $form.off('submit');
删除事件处理程序,然后使用 form.submit();
提交。遗憾的是,这也删除了我的 preventDoubleSubmission 事件处理程序,它允许再次提交两次。
有办法解决我的问题吗?谢谢
下面是带有正确解决方案的代码片段。您的原始方法存在多个问题,在代码段下方突出显示。最好在不同的代码游乐场中 运行 此代码段,其中 javascript 的操作有效,例如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>
编辑:添加说明
如果您直接在表单元素上绑定 'submit' 事件处理程序,$form.off()
会起作用,但在这两种情况下,处理程序都在文档中注册。
不需要调用 form.submit()
,因为我们已经在提交处理程序中,因此已经调用了提交。我们只需要阻止提交即可继续。
最好只有一个提交处理程序,并在那里处理双重提交。
e.preventDefault();
必须仅在未确认案例的 else 子句中和 submitOnce()
中。你在主处理程序的开头有它,但它在那里没用,因为 form.submit()
在内部再次调用,并且此调用不会阻止默认值。
我的方法并非万无一失,仅作为需要更改内容的示范。
一种方法是使用带有点击事件的普通跨度。单击后,您可以禁用它(例如使用 class),然后提交表单。这种方法允许您在不需要额外编码的情况下控制表单提交。
看这个例子:
$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>
所以我终于想出了一个对我来说比较好的解决方案。然而它很简单,我可能会坚持下去。
//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
}
});
它是如何工作的?
基本上我只是在提交后禁用提交按钮(=防止重复提交)。我在弹出窗口应显示的特定表单中添加了一个名为 form-confirm
的 class,因此一般规则在那里不起作用。
我总是在我的代码中使用 preventDefault
并使用 form.submit()
立即提交。
目前我的项目中 jQuery 表单提交有一些问题。
我的项目包含一个通用的 jQuery 代码,可以防止表单重复提交(例如,有人多次单击 'submit' 按钮)。
//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();
});
此代码包含在每个页面中 - 因此每个表单都应 'protected'。
对于某些特定的表单,我需要在提交之前检查一些值 - 如果缺少某些值,则显示确认框(例如,您确定要提交没有值 X 的表单吗?)
代码如下:
$(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();
}
});
所以基本上,如果用户尝试提交表单,但缺少值 X,则会首先出现一个 Yes/No 弹出窗口 - 如果该值存在,将立即提交表单。
问题:
当我想提交表单时,我调用 $form.off('submit');
删除事件处理程序,然后使用 form.submit();
提交。遗憾的是,这也删除了我的 preventDoubleSubmission 事件处理程序,它允许再次提交两次。
有办法解决我的问题吗?谢谢
下面是带有正确解决方案的代码片段。您的原始方法存在多个问题,在代码段下方突出显示。最好在不同的代码游乐场中 运行 此代码段,其中 javascript 的操作有效,例如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>
编辑:添加说明
如果您直接在表单元素上绑定 'submit' 事件处理程序,$form.off()
会起作用,但在这两种情况下,处理程序都在文档中注册。
不需要调用 form.submit()
,因为我们已经在提交处理程序中,因此已经调用了提交。我们只需要阻止提交即可继续。
最好只有一个提交处理程序,并在那里处理双重提交。
e.preventDefault();
必须仅在未确认案例的 else 子句中和 submitOnce()
中。你在主处理程序的开头有它,但它在那里没用,因为 form.submit()
在内部再次调用,并且此调用不会阻止默认值。
我的方法并非万无一失,仅作为需要更改内容的示范。
一种方法是使用带有点击事件的普通跨度。单击后,您可以禁用它(例如使用 class),然后提交表单。这种方法允许您在不需要额外编码的情况下控制表单提交。
看这个例子:
$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>
所以我终于想出了一个对我来说比较好的解决方案。然而它很简单,我可能会坚持下去。
//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
}
});
它是如何工作的?
基本上我只是在提交后禁用提交按钮(=防止重复提交)。我在弹出窗口应显示的特定表单中添加了一个名为 form-confirm
的 class,因此一般规则在那里不起作用。
我总是在我的代码中使用 preventDefault
并使用 form.submit()
立即提交。