2010-05-14 18 views
5

我使用jquery的.submit()拦截用户的提交事件,但是我发现了一个问题。使用jQuery来防止重新提交表格

当用户单击提交按钮时,表单被正常提交,但如果用户故意快速多次点击,则会多次提交,这会导致数据库中重复的数据。

这种问题的解决方案是什么?

更新:好吧,我看到一些建议说禁用提交按钮。这应该防止多次提交表单,但问题是我的页面中的表单元素没有刷新,如果我禁用它,用户将无法再提交它,禁用它15秒可能工作,但是这是解决这个问题的正确方法吗?

+0

您正在使用AJAX来提交表单...因为禁用是好的,如果不是阿贾克斯... – Reigel 2010-05-14 02:46:24

+0

是的,我使用jQuery的负载。当用户提交表单时,表中增加一行。 – Sawyer 2010-05-14 02:48:34

+0

再次看我的答案,如果它有帮助... – Reigel 2010-05-14 03:00:48

回答

7

禁用提交按钮确实是要走的路。

但是,在许多情况下,要执行的服务器端逻辑取决于请求参数映射中存在的问题提交按钮的名称 - 值对。特别是在基于服务器端组件的MVC框架(如MS ASP.NET和Sun JSF)中,而且在具有多个提交按钮的“简单”表单中。按下的提交按钮的名称 - 值对是确定要执行的操作的必需条件。禁用该按钮将使其名称 - 值对在请求参数映射中完全消失,并且服务器端可能不会采取任何操作或执行错误操作。

基本上有2种方式去解决这个:

  1. 使用setTimeout()后的几毫秒,这样它的名称 - 值对得到反正发送禁用按钮。 50ms是一个负担得起的金额。

    $("form").submit(function() { 
        var form = this; 
        setTimeout(function() { 
         $(':submit', form).attr('disabled', true); 
        }, 50); 
    }); 
    
  2. 将实际按下的提交按钮的名称 - 值对复制到表单的隐藏输入中。这有点棘手,因为这个信息在<form>submit事件中不可用。您需要让$(document)捕获最后点击的元素。

    $("form").submit(function() { 
        $(':submit', this).attr('disabled', true); 
        $(this).append($('<input/>').attr({ 
         type: 'hidden', 
         name: $.lastClicked.name, 
         value: $.lastClicked.value 
        })); 
    }); 
    
    $(document).click(function(e) { 
        e = e || event; 
        $.lastClicked = e.target || e.srcElement; 
    }); 
    

更新:根据您的更新:

嗯,我看到了一些意见表示禁用提交按钮。这应该防止提交多次,但问题是我的页面中的表单元素没有刷新,如果我禁用它,用户将无法再提交它,禁用它15秒可能会工作,但是这解决这个问题的正确方法?

所以你实际上是发射ajaxical请求。您可以在jQuery的ajax函数的回调处理程序中重新启用按钮。假设你正在使用jQuery.post

$("form").submit(function() { 
    // Disable buttons here whatever way you want. 

    var form = this; 
    $.post('some/url', function(data) { 
     // Re-enable buttons at end of the callback handler. 
     $(':submit', form).attr('disabled', false); 
    }); 
}); 
1

尝试禁用的形式提交按钮提交....

$("form").submit(function() { 
    $(':submit',this).attr('disabled','disabled'); 
    $('selector').load(url,function(){ 
     $(':submit',this).removeAttr('disabled'); 
    }) 
});​ 

quick demo

+0

谢谢你,看看我的更新! – Sawyer 2010-05-14 02:38:25

+0

什么是“url”?另外,不要忘记按Enter键提交表单。 – nickf 2010-05-14 03:19:52

+0

@nickf - 你想问我什么是'$('selector')'?... OP没有给出太多的代码(只是'.submit()')...所以我假设。如果文本框处于焦点状态,按下Enter键也会提交,然后按Enter键,但是再次输入则取决于OP的代码.... – Reigel 2010-05-14 03:37:03

0

真正的问题在于,在数据库层必须设计,以防止重复。这是一个普遍但有点难看的解决方案:

当您最初呈现一个页面时,您可以创建一个GUID。说,操作ID。并将其放入视图状态。当你在服务器端处理一个事件时,只需要将这个GUID插入到一个表中,就可以说它是主键的OngoingOperations。第一次插入会成功,其他插入将失败。为了更方便用户,您可以跳过后续操作并返回第一个状态。

的OngoingOperations表可以如下所示:

CREATE TABLE OngoingOperations( OperationID唯一标识符主键, OperationDate日期时间默认GETDATE(), OperationStatus为nvarchar(最大) );

OperationStatus - 状态消息或任何数据从后续提交返回给客户端。在这里你可以使用一个标志(好或不好)或一个详细的信息 - 如你所愿。

此表需要收集旧记录,比方说每小时您只需删除2小时或更长时间之前完成的操作。

安东Burtsev

0

试试这个:

$("form").submit(function() { 
    var form = this; 
    setTimeout(function() { 
     $(':submit', form).attr('disabled', true); 
    }, 50); 

    setTimeout(function() { 
     $(':submit', form).removeAttr('disabled'); 
    }, 1000); 
});