防止在jQuery中双重提交表单
我有一个表单需要一些时间来处理服务器。 我需要确保用户等待,而不是通过再次单击按钮尝试重新提交表单。 我尝试使用以下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中。 我需要通常提交的表单,并且在发生这种情况之后,我需要禁用所有的功能。
谢谢!
我认为你的问题是这样的:
$('input').attr('disabled','disabled');
你正在禁用所有的输入,包括我猜想,那些表单应该提交的数据。
要禁用提交按钮,您可以这样做:
$('button[type=submit], input[type=submit]').prop('disabled',true);
但是,我不认为即使这些按钮被禁用,IE也会提交表单。 我会建议一个不同的方法。
一个jQuery插件来解决它
我们用下面的代码解决了这个问题。 这里的诀窍是使用jQuery的data()
来标记已经提交或不提交的表单。 这样,我们就不必乱搞提交按钮,这吓坏了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中,当你禁用一个按钮时,当你回到历史中时,这个状态将被记住。 例如,要防止在页面加载时启用按钮。
我觉得Nathan Long的答案是要走的路。 对我来说,我正在使用客户端验证,所以我只是添加了一个条件,表单是有效的。
编辑 :如果没有添加,如果客户端验证遇到错误,用户将永远不能提交表单。
// 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; };
请检查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; } });
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; }); };
为了解决Kern31问题,计时方法适用于我,只是因为我们试图停止双击提交按钮。 如果您对提交的回复时间非常长,我建议您使用微调来替换提交按钮或表单。
完全封锁表格的后续提交,就像上面的大多数例子一样,有一个不好的副作用:如果网络发生故障,他们想要重新提交,他们将无法做到这一点,将失去他们的变化制作。 这肯定会让一个愤怒的用户。
…但表单没有提交任何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>
有可能改善Nathan Long的方法 。 你可以用这个替换已经提交的表单的检测逻辑:
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验证插件
如果你碰巧使用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内扩展它以禁用输入和/或提交按钮。
干杯
如果使用AJAX发布表单,设置async: 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; } });
对于Bootstrap 3,修改了Nathan的解决方案。这会将加载文本设置为提交按钮。 此外,它将在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); };
我最终使用这个帖子的想法来提出一个与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的时候会导致一些问题。
这可能可能有点小,因为它不那么花哨。
使用两个提交按钮。
<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(); });
我一直有类似的问题,我的解决方案如下。
如果您没有任何客户端验证,那么您可以简单地使用这里记录的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); } });
这里是我如何做到这一点:
$(document).ready(function () { $('.class_name').click(function () { $(this).parent().append('<img src="data:image/gif;base64,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" />'); $(this).hide(); }); });
学分: https : //github.com/phpawy/jquery-submit-once
这个代码会在按钮标签上显示加载,并将按钮设置为
禁用状态,然后处理后,重新启用并返回原来的按钮文本**
$(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 }
);
我的解决方案
// 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; };
我解决了一个非常类似的问题:
$("#my_form").submit(function(){ $('input[type=submit]').click(function(event){ event.preventDefault(); }); });