如何防止重复提交表单而不丢失任何数据? [英] How to prevent double form submit without losing any data?

查看:247
本文介绍了如何防止重复提交表单而不丢失任何数据?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个带有两个按钮的HTML表单

I have a HTML form with two buttons

<form action="...">
    ...
    <input type="submit" name="button1" value="Localized button 1">
    <input type="submit" name="button2" value="Otro botón">
<form>

以及以下JavaScript代码

and following JavaScript code

// prevent double submit and display a nice animation while submitting
$(document).on("submit", "form", function(event)
{
    $(this).find("input[type=submit], button").each(function()
    {
        var $button = $(this);
        $button.attr("disabled", "disabled");
        $button.addClass("submitting");
        setTimeout(function()
        {
            $button.removeAttr("disabled");
            $button.removeClass("submitting");
        }, 10000); // remove disabled status after timeout (ms)
    });
});

(加上一些CSS过渡和动画以使.submitting看起来不错)

(plus some CSS transitions and animations to make .submitting look nice)

上面的代码试图防止重复提交表单,因为有些人似乎对网络有误解,并经常双击常规表单提交按钮.其他一些人由于握手或鼠标键坏了而导致触摸屏出现问题,因此这也与可用性有关.

The above code tries to prevent double form submission because some people seem to misunderstand the web and keep double clicking normal form submit buttons. Some other people have problems with touchscreens due shaking hands or poorly working broken mouse buttons so this about usability, too.

问题是Google Chrome在收集要与表单提交一起发送的数据之前运行事件处理程序on("submit") .结果,如果禁用了不发送输入值的HTML5规则,则会妨碍该规则,并阻止任何提交按钮包含在服务器可以看到的请求中. (服务器正在寻找参数button1button2,但忽略了实际值,因为它是基于历史HTML格式规则的本地化字符串.)

The problem is that Google Chrome runs the event handler on("submit") before collecting the data to be sent with the form submission. As a result, the HTML5 rule of not sending the input value if its control is disabled gets in the way and prevents any submit buttons from being included in the request that the server can see. (The server is looking for parameter button1 or button2 but ignores actual value because it's a localized string due historical HTML form rules.)

如何在遵循HTML5规则的浏览器上禁用提交按钮,并且仍然获得有关实际按下的按钮的信息?我非常想拥有一个语义正确的HTML5源的解决方案.在表单数据已收集并即将传输到服务器之后,是否可以运行代码 ?

How to disable submit buttons on browsers that honor HTML5 rules and still get info about the actual button that was pressed? I very much want to have a solution that has semantically correct HTML5 source. Is there a way to run code after the form data has been collected and about to be transferred to the server?

有些相关的非重复项(请不要将其标记为任何这些重复项):

Somewhat related non-duplicates (please, do not flag this as duplicate of any of these):

  • Disabling double submit prevent sending submit name
  • Prevent double submits
  • Prevent double submit

其他要求:

  • 允许延迟一段时间(在上述示例中为10秒)后重新提交表单,以使用户能够解决例如网络连接中断或有意重复提交.
  • 没有恶意解决方案(例如,在实际的on("submit")事件之后,以较短的超时时间运行上述代码,希望浏览器已收集数据,但用户不够快,无法双击按钮.
  • 该表单仍应在禁用JavaScript的情况下正常工作-在这种情况下,可以避免双重表单提交,这是可以的.
  • 没有任何技巧,例如将包含缺少参数的隐藏表单输入添加到DOM中.
  • Allow re-submitting the form after a delay (10 sec in the example above) to allow user to workaround e.g. interrupted network connection or to do intentional double submission.
  • No racy solutions (e.g. running the above code with a short timeout after the actual on("submit") event hoping that the browser has collected the data but the user isn't fast enough to double click the button.
  • The form should still work with JavaScript disabled - not having double form submit prevention in this case is okay.
  • No hacks such as adding a hidden form input containing the missing parameter into the DOM.

推荐答案

这里的实现似乎足够健壮,可以用于生产环境:

Here's an implementation that seems to be robust enough for production use:

    // prevent double submit and display a nice animation while submitting
    $(document).on("submit", "form", function(event)
    {
        $(this).find("input[type=submit], button").each(function()
        {
            var $button = $(this);

            if ($button.attr("disabled"))
                return; // this button is already disabled, do not touch it

            setTimeout(function()
            {
                $button.attr("disabled", "disabled");
                $button.addClass("submitting");
                setTimeout(function()
                {
                    $button.removeAttr("disabled");
                    $button.removeClass("submitting");
                }, 10000); // remove disabled status after timeout (ms)
            }, 0); // let the event loop run before disabling the buttons to allow form submission to collect form data (and emit "formdata" event) before disabling any buttons and hope that user is not fast enough to double submit before this happens
        });
    });

setTimeout(..., 0)是一种黑客,可让Chrome运行一次事件循环,以使Chrome能够在我们禁用按钮之前收集表单数据,这会从提交的数据中删除有关按钮的信息.据我所知,这与用户输入无关,因为我们可以在此处使用0的延迟,并且用户无法以零延迟输入任何输入.

The setTimeout(..., 0) is a hack to allow Chrome to run its event loop once to get Chrome to collect the form data before we disable the buttons which would drop the info about the button from the submitted data. As far as I know, this is not racy with user input because we can use delay of 0 here and there's no way for user to enter any input with zero delay.

这篇关于如何防止重复提交表单而不丢失任何数据?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆