【问题标题】:Disable button on form submission表单提交时禁用按钮
【发布时间】:2010-09-11 12:20:04
【问题描述】:

我有一个按钮,我想在表单提交时禁用它以防止用户多次提交。

我曾尝试使用 javascript onclick 天真地禁用该按钮,但如果客户端验证失败,则该按钮仍处于禁用状态。

当表单成功提交时,我如何禁用按钮,而不仅仅是在用户点击时?

这是一个 ASP.NET 表单,所以如果可能的话,我想很好地融入 asp.net ajax 页面生命周期。

【问题讨论】:

    标签: asp.net javascript webforms


    【解决方案1】:

    在提交处理程序的最后禁用按钮。如果验证失败,它应该在此之前返回 false。

    但是,JavaScript 方法不是可以依赖的,因此您也应该有一些东西来检测服务器上的重复项。

    【讨论】:

      【解决方案2】:

      不确定这是否有帮助,但表单中有 onsubmit 事件。每当表单提交(从任何按钮或控件)时,您都可以使用此事件。 供参考:http://www.htmlcodetutorial.com/forms/_FORM_onSubmit.html

      【讨论】:

        【解决方案3】:

        以下功能很有用,无需禁用往往不可靠的部分。只需使用“return check_submit();”作为提交按钮的 onclick 处理程序的一部分。

        还应该有一个隐藏字段来保存form_submitted初始值0;

        <input type="hidden" name="form_submitted" value="0">
        
        function check_submit (){
                    if (document.Form1.form_submitted.value == 1){
                        alert("Don't submit twice. Please wait.");
                        return false;
                    }
                    else{
                        document.Form1.form_submitted.value = 1;
                        return true;
                    }
                    return false;
            }
        

        【讨论】:

        • 这里有很多很棒的答案,但这个很漂亮。
        【解决方案4】:

        解决方案是在单击按钮时设置一个隐藏字段,编号为 1。

        在按钮单击处理程序上,首先检查该数字是否不是 1,然后从函数中返回。

        【讨论】:

          【解决方案5】:

          您还可以利用表单上可用的 onsubmit() javascript 事件。此事件在表单实际提交时触发,并且在验证完成之前不应捕获。

          【讨论】:

            【解决方案6】:

            试一试:

            using System;
            using System.Collections.Generic;
            using System.Linq;
            using System.Web;
            using System.Web.UI;
            using System.Web.UI.WebControls;
            using System.Threading;
            
            public partial class _Default : System.Web.UI.Page 
            {
                protected void Page_Load(object sender, EventArgs e)
                {
            
                     // Identify button as a "disabled-when-clicked" button...
                     WebHelpers.DisableButtonOnClick( buttonTest, "showPleaseWait" ); 
                }
            
                protected void buttonTest_Click( object sender, EventArgs e )
                {
                    // Emulate a server-side process to demo the disabled button during
                    // postback.
                    Thread.Sleep( 5000 );
                }
            }
            
            
            
            using System;
            using System.Web;
            using System.Web.UI.WebControls;
            using System.Text;
            
            public class WebHelpers
            {
                //
                // Disable button with no secondary JavaScript function call.
                //
                public static void DisableButtonOnClick( Button ButtonControl )
                {
                    DisableButtonOnClick( ButtonControl, string.Empty );    
                }
            
                //
                // Disable button with a JavaScript function call.
                //
                public static void DisableButtonOnClick( Button ButtonControl, string ClientFunction )
                {   
                    StringBuilder sb = new StringBuilder( 128 );
            
                    // If the page has ASP.NET validators on it, this code ensures the
                    // page validates before continuing.
                    sb.Append( "if ( typeof( Page_ClientValidate ) == 'function' ) { " );
                    sb.Append( "if ( ! Page_ClientValidate() ) { return false; } } " );
            
                    // Disable this button.
                    sb.Append( "this.disabled = true;" ); 
            
                    // If a secondary JavaScript function has been provided, and if it can be found,
                    // call it. Note the name of the JavaScript function to call should be passed without
                    // parens.
                    if ( ! String.IsNullOrEmpty( ClientFunction ) ) 
                    {
                        sb.AppendFormat( "if ( typeof( {0} ) == 'function' ) {{ {0}() }};", ClientFunction );  
                    }
            
                    // GetPostBackEventReference() obtains a reference to a client-side script function 
                    // that causes the server to post back to the page (ie this causes the server-side part 
                    // of the "click" to be performed).
                    sb.Append( ButtonControl.Page.ClientScript.GetPostBackEventReference( ButtonControl ) + ";" );
            
                    // Add the JavaScript created a code to be executed when the button is clicked.
                    ButtonControl.Attributes.Add( "onclick", sb.ToString() );
                }
            }
            

            【讨论】:

            • rp.我必须做的一个小改动是将我的验证组名称传递给 Page_ClientValidate() 方法。感谢您的代码!
            • 我不是一个 ASP 人...但是写这么多代码而不是 onsubmit="this.button.disable=true" 或类似
              标签中的东西有点.. 。 诡异的? :|
            • Staicu:您的解决方案没有考虑验证是否通过。使用您的解决方案,如果验证失败,保存按钮将被禁用。
            • 很棒的代码,我最终将它作为我所有按钮的扩展方法。 public static void DisableButtonOnClick(this Button ButtonControl, string ClientFunction)
            • 需要 50 行服务器端代码来完成客户端的精妙操作?不,谢谢!!
            【解决方案7】:

            如果验证成功,则禁用该按钮。如果不是,那就不要。

            function validate(form) {
              // perform validation here
              if (isValid) {
                form.mySubmitButton.disabled = true;
                return true;
              } else {
                return false;
              }
            }
            
            <form onsubmit="return validate(this);">...</form>
            

            【讨论】:

              【解决方案8】:

              这是一种比rp 建议的更简单但类似的方法:

              function submit(button) {
                      Page_ClientValidate(); 
                      if(Page_IsValid)
                      {
                          button.disabled = true;
                      }
              }
              
               <asp:Button runat="server" ID="btnSubmit" OnClick="btnSubmit_OnClick" OnClientClick="submit(this)" Text="Submit Me" />
              

              【讨论】:

                【解决方案9】:

                将按钮的可见性设置为“无”;

                
                btnSubmit.Attributes("onClick") = document.getElementById('btnName').style.display = 'none';

                它不仅可以防止重复提交,而且可以向用户明确指示您不想多次按下按钮。

                【讨论】:

                • ...虽然我更喜欢使用 OnClientClick 属性,而不是代码隐藏。
                • ...如果客户端验证失败,您不需要它不会消失吗?
                【解决方案10】:

                我不太喜欢在代码隐藏中编写所有 javascript。这是我的最终解决方案。

                按钮:

                <asp:Button ID="btnSubmit" runat="server" Text="Submit" OnClick="btnSubmit_Click" OnClientClick="doSubmit(this)" />
                

                Javascript:

                <script type="text/javascript"><!--
                function doSubmit(btnSubmit) {
                    if (typeof(Page_ClientValidate) == 'function' && Page_ClientValidate() == false) { 
                        return false;
                    }    
                    btnSubmit.disabled = 'disabled';
                    btnSubmit.value = 'Processing. This may take several minutes...';
                    <%= ClientScript.GetPostBackEventReference(btnSubmit, string.Empty) %>;    
                }
                //-->
                </script>
                

                【讨论】:

                  【解决方案11】:

                  刚刚听说过

                  <asp:Button ID="submit" runat="server" Text="Save"
                      OnClick="yourClickEvent" DisableOnSubmit="true" />
                  

                  渲染时,按钮的 onclick 属性如下所示:

                  onclick="this.disabled=true; setTimeout('enableBack()', 3000);
                    WebForm_DoPostBackWithOptions(new
                    WebForm_PostBackOptions('yourControlsName', '', true, '', '', false, true))
                  

                  “enableBack()”javascript 函数如下所示:

                  function enableBack()
                  {
                      document.getElementById('yourControlsName').disabled=false;
                  }
                  

                  所以当按钮被点击时,它会被禁用 3 秒。如果表单成功发布,那么您永远不会看到重新启用按钮。但是,如果任何验证器失败,则该按钮会在 3 秒后再次启用。

                  这一切只需在按钮上设置一个属性——无需手动编写任何 JavaScript 代码。

                  【讨论】:

                  • 那太好了 - 但它在我的 ASP.NET 版本中不存在。你用的是什么版本!?
                  • 当时我使用的是最新版本:Visual Studio 2008。我不再为该雇主工作,因此无法验证其他任何内容(服务包、.NET 运行时版本等) .抱歉延迟回复!
                  • 现在想起来,我相信页面使用了AJAX,所以这可能是工具包提供的扩展。
                  【解决方案12】:

                  请注意,如果您使用带有UseSubmitBehavior="false" 的按钮,rp 的方法会双重提交您的表单。

                  我使用 rp 代码的以下变体:

                  public static void DisableButtonOnClick(Button button, string clientFunction)
                  {
                      // If the page has ASP.NET validators on it, this code ensures the
                      // page validates before continuing.
                      string script = "if (typeof(Page_ClientValidate) == 'function') { "
                              + "if (!Page_ClientValidate()) { return false; } } ";
                  
                      // disable the button
                      script += "this.disabled = true; ";
                  
                      // If a secondary JavaScript function has been provided, and if it can be found, call it.
                      // Note the name of the JavaScript function to call should be passed without parens.
                      if (!string.IsNullOrEmpty(clientFunction))
                          script += string.Format("if (typeof({0}) == 'function') {{ {0}() }} ", clientFunction);
                  
                      // only need to post back if button is using submit behaviour
                      if (button.UseSubmitBehavior)
                          script += button.Page.GetPostBackEventReference(button) + "; ";
                  
                      button.Attributes.Add("onclick", script);
                  }
                  

                  【讨论】:

                    【解决方案13】:

                    正确的(至少就用户友好性而言)方法是使用 OnClientClick 属性禁用按钮,执行客户端验证,然后使用其结果继续或重新启用按钮。

                    当然,您还应该为此编写服务器端代码,因为即使由于 JavaScript 的缺乏或特定实现,您也不能依赖验证。但是,如果您依赖服务器控制按钮的启用/禁用状态,那么您基本上无法阻止用户多次提交表单。出于这个原因,您应该有某种逻辑来检测同一用户在短时间内的多次提交(例如,来自同一会话的相同值)。

                    【讨论】:

                      【解决方案14】:

                      我的一个解决方案如下:

                      在您的 aspx 文件的 page_load 中添加脚本

                          HtmlGenericControl includeMyJava = new HtmlGenericControl("script");
                          includeMyJava.Attributes.Add("type", "text/javascript");
                          includeMyJava.InnerHtml = "\nfunction dsbButton(button) {";
                          includeMyJava.InnerHtml += "\nPage_ClientValidate();";
                          includeMyJava.InnerHtml += "\nif(Page_IsValid)";
                          includeMyJava.InnerHtml += "\n{";
                          includeMyJava.InnerHtml += "\nbutton.disabled = true;";
                          includeMyJava.InnerHtml += "}";
                          includeMyJava.InnerHtml += "\n}";
                          this.Page.Header.Controls.Add(includeMyJava);
                      

                      然后设置你的aspx按钮参数如下:

                      <asp:Button ID="send" runat="server" UseSubmitBehavior="false" OnClientClick="dsbButton(this);" Text="Send" OnClick="send_Click" />
                      

                      请注意,“onClientClick”有助于禁用按钮,“UseSubmitBehaviour”禁用页面的传统提交行为,并允许asp.net在用户脚本上呈现提交行为。

                      祝你好运

                      -瓦卡斯阿斯拉姆

                      【讨论】:

                        【解决方案15】:

                        因此,简单地通过 javascript 禁用按钮不是跨浏览器兼容的选项。如果您只使用 OnClientClick="this.disabled=true;"
                        ,Chrome 将不会提交表单 以下是我在 Firefox 9、Internet Explorer 9 和 Chrome 16 中测试过的解决方案:

                        <script type="text/javascript">
                        var buttonToDisable;
                        function disableButton(sender)
                        {
                            buttonToDisable=sender;
                            setTimeout('if(Page_IsValid==true)buttonToDisable.disabled=true;', 10);
                        }
                        </script>
                        

                        然后使用表单提交按钮的单击事件注册“disableButton”,一种方法是:

                        <asp:Button runat="server" ID="btnSubmit" Text="Submit" OnClientClick="disableButton(this);" />
                        

                        值得注意的是,如果客户端验证失败,这可以解决您的按钮被禁用的问题。也不需要服务器端处理。

                        【讨论】:

                          【解决方案16】:

                          基于@rp. 的回答,我对其进行了修改以调用自定义函数,并在成功时提交和禁用或在错误时“停止”:

                          public static void DisableButtonOnClick(Button ButtonControl, string ClientFunction)
                          {
                              StringBuilder sb = new StringBuilder(128);
                          
                              if (!String.IsNullOrEmpty(ClientFunction))
                              {
                                  sb.AppendFormat("if (typeof({0}) == 'function') {{ if ({0}()) {{ {1}; this.disabled=true; return true; }} else {{ return false; }} }};", ClientFunction, ButtonControl.Page.ClientScript.GetPostBackEventReference(ButtonControl, null));
                              }
                              else
                              {
                                  sb.Append("return true;");
                              }
                          
                              ButtonControl.Attributes.Add("onclick", sb.ToString());
                          }
                          

                          【讨论】:

                            【解决方案17】:

                            在我们的一个遗留应用程序中遇到了 rp 的代码,该应用程序正在与一些疯狂的行为作斗争。

                            跟踪到一个奇怪的事件触发组合 - 当 DisableButtonOnClick() 在 UpdatePanel 内的 asp 按钮上使用时,POST 将被发送两次(一次由 DisableButtonOnClick() 添加的 doPostBack,一次由更新面板)。但是,这只发生在某些浏览器上(Edge 的早期版本,但不是最近的版本,IE11 做到了这一点,Chrome 和 FireFox 没有(至少我测试过的版本))。我认为 Chrome 和更新版本的 Edge 正在以某种方式在内部处理这种情况。在 IE 中使用 F12 devtools 跟踪问题 - 这两个 POST 发生得如此紧密,以至于第一个 POST 立即中止,但在某些情况下(网络延迟、用户机器负载等),请求确实在浏览器可以之前到达服务器中止。因此,这导致整个系统中的按钮按下看似随机的双张贴,追溯起来很痛苦。解决方法是添加一个“return false;”在 doPostBack 之后,以防止 UpdatePanel 在旧浏览器运行时参与其中。

                            TLDR - 请注意更新面板中按钮上的此代码。这是一个很好的方法和很好的方法,但在我(可能是边缘)的情况下有一个潜在的问题。

                            ps - 我会评论 rp 的帖子,但我没有代表。认为它可能对未来的旅行者有用。

                            【讨论】:

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