【问题标题】:Disable button on form submission but post button value禁用表单提交按钮但发布按钮值
【发布时间】:2014-10-28 08:39:08
【问题描述】:

我想阻止多个表单提交,但我需要将提交元素的值回传到服务器(以便我知道用户点击了哪个按钮)。

大多数关于抑制多个表单提交的 Internet 智慧似乎都涉及在表单提交期间禁用提交按钮。这可以防止按钮被第二次点击,但也防止其值被发布。

我发现了一些隐藏提交按钮的 JS 代码示例,它允许发布它们的值。但是这些示例都用某种“处理...”消息替换了(现在隐藏的)按钮。我真的想要一个解决方案,向用户显示一个禁用的按钮,但仍然发布按钮值。

我应该补充一点,我更喜欢一种可以在大多数表单中找到的标准 HTML 的解决方案。没有神奇的 IFrame、隐藏字段、id 或类名等。我想要一个 JS 函数,我可以把它藏在一个库中,并从我所有现有的表单中引用来启用这种新行为。

(我有一个解决方案,我将作为答案发布。但我必须提出这个问题以符合 SO 的禅宗。)

【问题讨论】:

  • 您可以使用jsfiddle.net 创建您的代码演示并分享吗?这样会更有帮助!
  • 只是出于好奇,您为什么需要知道首先点击了哪个提交按钮?通常每个表单只有一个提交按钮。例如,您是否有多个采用相同参数的动作,而只是不想设置多个相同的表单?
  • 我通常至少有两个按钮:“确定”和“取消”。有时我可能还会有类似“

标签: javascript jquery html forms


【解决方案1】:

这里(又一个)回答了如何处理防止用户多次点击表单提交按钮的问题。此解决方案显示该按钮已被禁用。

在幕后,它创建了一个禁用按钮以向用户显示,并隐藏实际按钮以便发布其值。我还移动了隐藏按钮,这样额外的元素就不会弄乱 CSS 选择器。

还要注意检查无效表单字段。如果您忽略此检查,并且表单验证失败,那么用户最终会得到一个未发布的表单(因为客户端验证失败)但按钮被禁用。

// Disables buttons when form is submitted
$('form').submit(function () {
    // Bail out if the form contains validation errors
    if ($.validator && !$(this).valid()) return;

    var form = $(this);
    $(this).find('input[type="submit"], button[type="submit"]').each(function (index) {
        // Create a disabled clone of the submit button
        $(this).clone(false).removeAttr('id').prop('disabled', true).insertBefore($(this));

        // Hide the actual submit button and move it to the beginning of the form
        $(this).hide();
        form.prepend($(this));
    });
});

【讨论】:

    【解决方案2】:

    这里有几个选项:

    1.您可以创建隐藏输入并在提交表单之前动态更改其值,无论是 onClick 还是所述按钮的 onHover:

    2. 您可以创建一个隐藏的 iframe,它是上述表单的目标。单击提交按钮后,您可以取消提交事件,获取所有数据并通过 iframe 以编程方式发送。

    【讨论】:

    • Re: #1,我想我应该在 OP 中明确说明我想要一个不涉及额外(隐藏)表单字段或魔术 id 或类值的解决方案。
    【解决方案3】:

    因为除了单击提交按钮之外,您还可以通过其他方式提交表单,因此最好将侦听器添加到表单的提交事件而不是提交按钮上的单击事件。这个 jQuery 事件监听器应该在任何表单上工作并防止它被多次提交。

    $('form').on('submit', function(e) {
        if (!$(this).data('submitted')) {
            $(this).data('submitted', true);
        }
        else {
            e.preventDefault();
        }
    });
    

    要使表单看起来被禁用,您可以添加一些使表单看起来被禁用的 css,然后在表单提交时添加类名。

    $('form').on('submit', function(e) {
        if (!$(this).data('submitted')) {
            $(this).data('submitted', true).addClass('disabled');
        }
        else {
            e.preventDefault();
        }
    });
    

    【讨论】:

      【解决方案4】:

      您可以模拟禁用的外观行为。例如。如果你有这样的按钮:

      <input id="btn" type="button" onclick="disableMe(this)" value="Submit" />
      

      你可以这样定义 CSS

      .disabled {
          backround-color:grey;
          color:darkgrey;
      }
      

      还有这样的JS

      function disableMe(btn) {
          btn.className = "disabled";
          btn.onclick = function(){return false}
      }
      

      会发生什么 - 在第一次点击按钮将变为灰色(通过应用的 CSS)并且 onclick 事件将更改为“返回 false”,以防止未来的点击操作。该按钮将出现并作为禁用,但不会,因此不会阻止按钮提交。

      【讨论】:

        【解决方案5】:

        我想通过双击提交按钮或按两次回车键来阻止用户提交多个表单。我喜欢这个解决方案,因为它不需要隐藏表单字段或隐藏提交按钮。

        两个关键点是:

        1. 返回 true/false 而不是使用 e.preventDefault() 和 form.submit(),因为 form.submit() 不知道点击了哪个按钮,因此无法传递按钮名称/价值。

        2. 使用 pointer-events: none; 而不是 disabled="disabled" 禁用按钮,因为 disabled 属性不会发送按钮名称/值。我相信 Internet Explorer 10 或更低版本不支持pointer-events: none;

        javascript/jquery 代码:

        var form_selector = 'form',
            button_selector = 'button, input[type=submit], input[type=button], input[type=reset]',
            deactivated_classname = 'state-submitting',
            deactivated_class = '.'+'state-submitting';
        
        // Capture the submit event so it will handle both the 
        // enter key and clicking the submit button.
        $(document).on('submit', form_selector, function(e) {
          var form = e.target,
              buttons = $( form ).find( button_selector );
        
          // Returns, because the form is already being submitted by a previous attempt.
          if( $( form ).find( deactivated_class ).length > 0  ) return false;
        
          disableButtons( buttons );
        
          // Safari (version 11) bugfix: Safari needs a timeout or it won't 
          // show the deactivated styles.
          setTimeout(function() {
            // Must use return true, because using form.submit(), won't pass the button value.
            return true;
          }, 50 );
        });
        
        function disableButtons( buttons ) {
          // Disables all buttons in the form.
          $( buttons ).each(function( index, elem ) {
            $( elem ).addClass( deactivated_classname );
          });
        }
        

        对于 AJAX 表单,您需要在返回响应后重新启用按钮。

        $( document ).on( 'ajax:complete', form_selector, function(e) {
          var form = e.target,
              buttons = $( form ).find( button_selector );
        
          enableButtons( buttons );
        });
        
        function enableButtons( buttons ) {
          $( buttons ).each(function( index, elem ) {
            $( elem ).removeClass( deactivated_classname );
          });
        }
        

        CSS:

        // The button is disabled while it is submitting.
        .state-submitting {   
          // Turns off hover and click events. Not supported in IE 10 and below.
          pointer-events: none;
          opacity: 0.5;
        }
        

        【讨论】:

        • 做得好这个“指针事件:无;不透明度:0.5;”它非常干净,效果很好。我对此的解决方案是: $ ('form').submit (function (event) { if ($ (this).valid ()) { $(':submit', this).css({'pointer-events' :'none', 'opacity': '0.5'}); } return true; });
        【解决方案6】:

        我遇到了与 OP 相同的问题,我发现通过 setTimeout 在短暂(可能为 0 秒)超时后禁用提交按钮可以解决问题。提交按钮的名称值仍会根据需要与其余的表单数据一起发布,但按钮会立即(几乎)禁用自身,从而阻止进一步的点击。

        超时有点难看,但似乎比更复杂的交换/覆盖方案更可取。

        这可以与更改表单的onsubmit 属性相结合,以提供额外的预防措施,但为了清楚起见,我在下面的示例中没有这样做。无论哪种方式,我都喜欢第一次提交点击后禁用按钮的外观/行为……用户体验对我来说似乎更好……更清楚发生了什么。

        我的表单元素的开始标签:

        <form onsubmit="return formSubmit(this);" method="post" action="">
        

        在我的 JavaScript 中(抱歉,我不了解最新的 JS 技术,如 jQuery 等,所以我将其发布在 old-fashioned-native-JavaScript-5-with-no-dependencies -兼容代码):

        function formSubmit(form) {
            // MUST DELAY so as not to break input/button[type=submit] name submission
            setTimeout(function () {
                var els = form.elements;
                for (var i = 0; i < els.length; i++) {
                    var el = els[i];
                    if (el.getAttribute('type') == 'submit') {
                        el.setAttribute('disabled', 'disabled');
                    }
                }
            }, 0);
            return true;
        }
        

        【讨论】:

          【解决方案7】:

          我认为更好的解决方案是使用 JQuery :

          <form onsubmit="$('#submit').hide();" method="post" action="">
          

          没有机会双击。 有时我们在提交按钮中使用名称字段进行验证,因此如果禁用此功能,则可能会失败。 使用 .hide() 按钮将被隐藏。 所以没有机会双击它。

          【讨论】:

            【解决方案8】:

            老实说,我无法完全理解此页面上的大部分帖子,但我想我以前遇到过这个问题,并通过允许页面在第一次单击按钮时发布来解决它,所以当页面从服务器返回时,它具有分配给它的新值,它看起来可点击并启用。但是如果第二次尝试按下它,它就会被禁用,并且页面将不会发布,并通过单击此按钮再次发送到服务器。我希望这会有所帮助:

            @section scripts
            {
              <script type="text/javascript">
                $('#edit').click(function () {
                  if (document.getElementById("edit").value == '') { 
                    // This portion should execute onlythe 
                    // first time button is clicked, and it 
                    // will assign a new value to the button, 
                    //and posts the value 
                    //to the server
                  }
                  else {  
                    edit.disabled = true; 
                  }
                });
              </script>               
            }
            

            【讨论】:

              【解决方案9】:

              一个更简单的方法是将用于禁用按钮的任何代码包含在 setTimeout() 中,延迟为 0。这样,按钮在处理表单提交的线程中仍处于启用状态,而另一个并行线程被生成来执行禁用。

              示例(使用 jQuery):

              <form method="POST" onsubmit="javascript:setTimeout(() => $('*[type=submit]', this).attr('disabled', 'disabled'), 0)">
              

              【讨论】:

                猜你喜欢
                • 2014-04-30
                • 2016-04-03
                • 2018-10-12
                • 2010-09-11
                • 1970-01-01
                • 1970-01-01
                • 2018-06-30
                • 1970-01-01
                相关资源
                最近更新 更多