我的表单需要服务器处理一些时间。我需要确保用户等待并且不会再次单击按钮来尝试重新提交表单。我尝试使用以下jQuery代码:
<script type="text/javascript">
$(document).ready(function() {
$("form#my_form").submit(function() {
$('input').attr('disabled', 'disabled');
$('a').attr('disabled', 'disabled');
return true;
});
});
</script>
当我在Firefox中尝试此操作时,所有功能均被禁用,但该表单未与应该包含的任何POST数据一起提交。我不能使用jQuery提交表单,因为我需要将按钮与表单一起提交,因为有多个提交按钮,并且我确定POST包含哪个值使用了哪个。我需要像平常一样提交表单,并且在发生这种情况后我需要立即禁用所有内容。
谢谢!
2018年更新:我对这个旧答案有几点看法,只是想补充一点,最好的解决方案是使操作具有幂等性,以便重复提交无害。
例如,如果表单创建了订单,则在表单中放置一个唯一的ID。服务器首次看到具有该ID的订单创建请求时,应创建该请求并响应“成功”。随后的提交也应回复“成功”(以防客户未获得第一个回复),但不应进行任何更改。
应该通过数据库中的唯一性检查来检测重复项,以防止出现竞争情况。
我认为您的问题是这一行:
$('input').attr('disabled','disabled');
您正在禁用所有输入,包括我认为应该提交其数据的输入。
要仅禁用提交按钮,可以执行以下操作:
$('button[type=submit], input[type=submit]').prop('disabled',true);
但是,即使禁用了那些按钮,我也不认为IE会提交表单。我建议使用另一种方法。
一个jQuery插件来解决
我们只是使用以下代码解决了这个问题。这里的技巧是使用jQuerydata()
将表单标记为已提交或未提交。这样,我们就不必弄乱提交按钮,这会使IE变得异常糟糕。
// jQuery plugin to prevent double submission of forms
jQuery.fn.preventDoubleSubmission = function() {
$(this).on('submit',function(e){
var $form = $(this);
if ($form.data('submitted') === true) {
// Previously submitted - don't submit again
e.preventDefault();
} else {
// Mark it so that the next submit can be ignored
$form.data('submitted', true);
}
});
// Keep chainability
return this;
};
像这样使用它:
$('form').preventDoubleSubmission();
如果应允许AJAX表单在每次加载页面时提交多次,则可以给它们提供一个类来指示该表单,然后将其从选择器中排除,如下所示:
$('form:not(.js-allow-double-submission)').preventDoubleSubmission();
计时方法是错误的-您如何知道该操作将在客户端的浏览器上执行多长时间?
怎么做
$('form').submit(function(){
$(this).find(':submit').attr('disabled','disabled');
});
提交表单后,它将禁用其中的所有提交按钮。
请记住,在Firefox中,当您禁用按钮时,当您返回历史记录时,该状态将被记住。例如,为防止这种情况,您必须启用页面加载按钮。
我认为内森·朗的答案是正确的方法。对我来说,我正在使用客户端验证,所以我只是添加了一个条件,要求该表单有效。
编辑:如果未添加,则如果客户端验证遇到错误,则用户将永远无法提交表单。
// jQuery plugin to prevent double submission of forms
jQuery.fn.preventDoubleSubmission = function () {
$(this).on('submit', function (e) {
var $form = $(this);
if ($form.data('submitted') === true) {
// Previously submitted - don't submit again
alert('Form already submitted. Please wait.');
e.preventDefault();
} else {
// Mark it so that the next submit can be ignored
// ADDED requirement that form be valid
if($form.valid()) {
$form.data('submitted', true);
}
}
});
// Keep chainability
return this;
};
event.timeStamp
在Firefox中不起作用。返回false是非标准的,您应该致电event.preventDefault()
。而且,在进行此操作时,请始终在控制结构中使用花括号。
总结所有先前的答案,这是一个可以完成工作并可以跨浏览器工作的插件。
jQuery.fn.preventDoubleSubmission = function() {
var last_clicked, time_since_clicked;
jQuery(this).bind('submit', function(event) {
if(last_clicked) {
time_since_clicked = jQuery.now() - last_clicked;
}
last_clicked = jQuery.now();
if(time_since_clicked < 2000) {
// Blocking form submit because it was too soon after the last submit.
event.preventDefault();
}
return true;
});
};
为了解决Kern3l,计时方法对我有用,仅因为我们试图停止双击“提交”按钮。如果您对提交的响应时间很长,建议您使用微调框替换提交按钮或表单。
就像上面的大多数示例一样,完全阻止后续提交表单会带来负面影响:如果网络出现故障并且他们想尝试重新提交,则他们将无法这样做,并且将丢失所做的更改制作。这肯定会使用户生气。
请检查jquery-safeform插件。
用法示例:
$('.safeform').safeform({
timeout: 5000, // disable next submission for 5 sec
submit: function() {
// You can put validation and ajax stuff here...
// When done no need to wait for timeout, re-enable the form ASAP
$(this).safeform('complete');
return false;
}
});
...但是表单未提交任何应该包含的POST数据。
正确。禁用的表单元素名称/值将不会发送到服务器。您应该将它们设置为只读元素。
同样,锚不能像这样被禁用。您将需要删除其HREF(不推荐)或防止其默认行为(更好的方式),例如:
<script type="text/javascript">
$(document).ready(function(){
$("form#my_form").submit(function(){
$('input').attr('readonly', true);
$('input[type=submit]').attr("disabled", "disabled");
$('a').unbind("click").click(function(e) {
e.preventDefault();
// or return false;
});
});
</script>
有可能改善内森·朗的方法。您可以用以下代码替换检测已提交表单的逻辑:
var lastTime = $(this).data("lastSubmitTime");
if (lastTime && typeof lastTime === "object") {
var now = new Date();
if ((now - lastTime) > 2000) // 2000ms
return true;
else
return false;
}
$(this).data("lastSubmitTime", new Date());
return true; // or do an ajax call or smth else
Nathan的代码,但适用于jQuery Validate插件
如果您碰巧使用jQuery Validate插件,则它们已经实现了提交处理程序,在这种情况下,没有理由实现多个。代码:
jQuery.validator.setDefaults({
submitHandler: function(form){
// Prevent double submit
if($(form).data('submitted')===true){
// Previously submitted - don't submit again
return false;
} else {
// Mark form as 'submitted' so that the next submit can be ignored
$(form).data('submitted', true);
return true;
}
}
});
您可以轻松地在} else {
-block中将其展开以禁用输入和/或提交按钮。
干杯
我最终根据这篇文章中的想法提出了与AtZako版本非常相似的解决方案。
jQuery.fn.preventDoubleSubmission = function() {
var last_clicked, time_since_clicked;
$(this).bind('submit', function(event){
if(last_clicked)
time_since_clicked = event.timeStamp - last_clicked;
last_clicked = event.timeStamp;
if(time_since_clicked < 2000)
return false;
return true;
});
};
像这样使用:
$('#my-form').preventDoubleSubmission();
我发现不包含某种超时但仅禁用提交或禁用表单元素的解决方案会引起问题,因为一旦触发锁定,您将无法再次提交,除非刷新页面。这在做ajax时给我带来一些问题。
这可能有点花哨,因为它不那么花哨。
如果使用AJAX发布表单,则setasync: false
应该防止在表单清除之前进行其他提交:
$("#form").submit(function(){
var one = $("#one").val();
var two = $("#two").val();
$.ajax({
type: "POST",
async: false, // <------ Will complete submit before allowing further action
url: "process.php",
data: "one="+one+"&two="+two+"&add=true",
success: function(result){
console.log(result);
// do something with result
},
error: function(){alert('Error!')}
});
return false;
}
});
稍微修改了Nathan针对Bootstrap 3的解决方案。这会将加载文本设置为Submit按钮。此外,它将在30秒后超时,并允许重新提交表单。
jQuery.fn.preventDoubleSubmission = function() {
$('input[type="submit"]').data('loading-text', 'Loading...');
$(this).on('submit',function(e){
var $form = $(this);
$('input[type="submit"]', $form).button('loading');
if ($form.data('submitted') === true) {
// Previously submitted - don't submit again
e.preventDefault();
} else {
// Mark it so that the next submit can be ignored
$form.data('submitted', true);
$form.setFormTimeout();
}
});
// Keep chainability
return this;
};
jQuery.fn.setFormTimeout = function() {
var $form = $(this);
setTimeout(function() {
$('input[type="submit"]', $form).button('reset');
alert('Form failed to submit within 30 seconds');
}, 30000);
};
使用两个提交按钮。
<input id="sub" name="sub" type="submit" value="OK, Save">
<input id="sub2" name="sub2" type="submit" value="Hidden Submit" style="display:none">
和jQuery:
$("#sub").click(function(){
$(this).val("Please wait..");
$(this).attr("disabled","disabled");
$("#sub2").click();
});
在提交时使用简单的计数器。
var submitCounter = 0;
function monitor() {
submitCounter++;
if (submitCounter < 2) {
console.log('Submitted. Attempt: ' + submitCounter);
return true;
}
console.log('Not Submitted. Attempt: ' + submitCounter);
return false;
}
并调用monitor()
函数提交表单。
<form action="/someAction.go" onsubmit="return monitor();" method="POST">
....
<input type="submit" value="Save Data">
</form>
我遇到过类似的问题,我的解决方案如下。
如果您没有任何客户端验证,则只需使用此处记录的jquery one()方法即可。
这将在调用处理程序后将其禁用。
$("#mysavebuttonid").on("click", function () {
$('form').submit();
});
如果您像我一样在进行客户端验证,那么它会比较棘手。上面的示例不允许您在验证失败后再次提交。尝试这种方法
$("#mysavebuttonid").on("click", function (event) {
$('form').submit();
if (boolFormPassedClientSideValidation) {
//form has passed client side validation and is going to be saved
//now disable this button from future presses
$(this).off(event);
}
});
您可以以此停止第二次提交
$("form").submit(function() {
// submit more than once return false
$(this).submit(function() {
return false;
});
// submit once return true
return true; // or do what you want to do
});
});
我的解决方案:
// jQuery plugin to prevent double submission of forms
$.fn.preventDoubleSubmission = function () {
var $form = $(this);
$form.find('[type="submit"]').click(function () {
$(this).prop('disabled', true);
$form.submit();
});
// Keep chainability
return this;
};
在我的情况下,表单的onsubmit有一些验证代码,因此我增加了Nathan Long的答案,包括一个onsubmit检查点
$.fn.preventDoubleSubmission = function() {
$(this).on('submit',function(e){
var $form = $(this);
//if the form has something in onsubmit
var submitCode = $form.attr('onsubmit');
if(submitCode != undefined && submitCode != ''){
var submitFunction = new Function (submitCode);
if(!submitFunction()){
event.preventDefault();
return false;
}
}
if ($form.data('submitted') === true) {
/*Previously submitted - don't submit again */
e.preventDefault();
} else {
/*Mark it so that the next submit can be ignored*/
$form.data('submitted', true);
}
});
/*Keep chainability*/
return this;
};
更改提交按钮:
<input id="submitButtonId" type="submit" value="Delete" />
使用普通按钮:
<input id="submitButtonId" type="button" value="Delete" />
然后使用点击功能:
$("#submitButtonId").click(function () {
$('#submitButtonId').prop('disabled', true);
$('#myForm').submit();
});
并记住在必要时重新启用按钮:
$('#submitButtonId').prop('disabled', false);
我不敢相信指针事件的老式CSS技巧:还没有人提及。通过添加禁用的属性,我遇到了同样的问题,但这并不会发回。请尝试以下操作,并将#SubmitButton替换为您提交按钮的ID。
$(document).on('click', '#SubmitButton', function () {
$(this).css('pointer-events', 'none');
})
为什么不这样做-这将提交表单,但也禁用了提交按钮,
$('#myForm').on('submit', function(e) {
var clickedSubmit = $(this).find('input[type=submit]:focus');
$(clickedSubmit).prop('disabled', true);
});
另外,如果您使用的是jQuery Validate,则可以将这两行放在下if ($('#myForm').valid())
。
此代码将在按钮标签上显示加载,并将按钮设置为
禁用状态,然后进行处理后,重新启用并返回原始按钮文本**
$(function () {
$(".btn-Loading").each(function (idx, elm) {
$(elm).click(function () {
//do processing
if ($(".input-validation-error").length > 0)
return;
$(this).attr("label", $(this).text()).text("loading ....");
$(this).delay(1000).animate({ disabled: true }, 1000, function () {
//original event call
$.when($(elm).delay(1000).one("click")).done(function () {
$(this).animate({ disabled: false }, 1000, function () {
$(this).text($(this).attr("label"));
})
});
//processing finalized
});
});
});
// and fire it after definition
});
我使用以下方法解决了一个非常类似的问题:
$("#my_form").submit(function(){
$('input[type=submit]').click(function(event){
event.preventDefault();
});
});
文章标签:double-submit-prevention , forms , http-post , javascript , jquery
版权声明:本文为原创文章,版权归 javascript 所有,欢迎分享本文,转载请保留出处!
评论已关闭!