【问题标题】:ASP.NET MVC - How to prevent double click submit with jquery.validate.unobtrusive lib?ASP.NET MVC - 如何使用 jquery.validate.unobtrusive lib 防止双击提交?
【发布时间】:2011-05-31 04:07:28
【问题描述】:

我需要避免双击提交行为。我将客户端验证与不显眼的库一起使用。我有以下代码可以避免双重点击:

jQuery.fn.preventDoubleSubmit = function () {
         var alreadySubmitted = false;
         return jQuery(this).submit(function () {

             if (alreadySubmitted)
                 return false;
             else {
                 alreadySubmitted = true;
             }
         });
     };

     jQuery('form').preventDoubleSubmit();

不幸的是,如果我的表单有一些有效的字段(例如,必填字段),上面的代码仍然会被触发,因此,即使我更正了表单上的任何错误,我也无法提交它再次。

验证成功后如何触发双击代码?

【问题讨论】:

    标签: asp.net-mvc-3 double-submit-prevention unobtrusive


    【解决方案1】:

    我用下面的代码解决了:

    var tryNumber = 0;
     jQuery('input[type=submit]').click(function (event) {
         var self = $(this);
    
         if (self.closest('form').valid()) {
             if (tryNumber > 0) {
                 tryNumber++;
                 alert('Your form has been already submited. wait please');
                 return false;
             }
             else {
                 tryNumber++;
             }
         };
     });
    

    注意:您也可以替换:

    return false;
    

    行,用于:

    self.attr('disabled', true);
    

    但是,如果您将控制器上的提交按钮的名称用于额外的逻辑,它们将作为 null 发送。 (您可以在提交前使用额外的隐藏字段向他们收费)

    就是这样,希望对你有帮助

    罗德里戈

    编辑:感谢这些帖子: jquery newbie: combine validate with hidding submit button

    【讨论】:

      【解决方案2】:

      您也可以使用 JQuery One event

      我发现我可以通过快速双击来绕过大多数防止双击的防护措施。使用一个事件是确保事件只被触发一次的唯一真正方法。我认为这种技术不会在输入 type=submit 标记的情况下“开箱即用”。相反,您可以简单地使用输入 type=button 或 JQueryUI's .button()

      $("#submitButton").one("click", function(event) {
         $('#theForm').submit();
      });
      

      如果您需要在验证错误(或其他情况)时重新连接事件,我建议您为事件处理程序创建一个函数。此示例中不需要该函数,因为事件处理程序所做的只是提交表单,但在更复杂的场景中,您可能希望避免重复自己。

      function submitClick(event) {
         $('#theForm').submit();
      }
      
      $("#submitButton").one('click', function(event) {
         submitClick(event);
      });
      
      // This handler will re-wire the event when the form is invalid.
      $('#theForm').submit(function(event) {
         if (!$(this).valid()) {
            event.preventDefault();
            $('#submitButton').one('click', function(event) { submitClick(event); });
         }
      });
      

      如果您想向用户提供按钮不再起作用的反馈,您显然可以在此处添加禁用代码。使用 One 事件的一个很好的副作用是您实际上不必禁用按钮,您可以使用自己的样式。

      function submitClick(event) {
         $('#submitButton').addClass('disabledButton');
         $('#theForm').submit();
      }
      
      $("#submitButton").one('click', function(event) {
         submitClick(event);
      });
      
      // This handler will re-wire the event when the form is invalid.
      $('#theForm').submit(function(event) {
         if (!$(this).valid()) {
            event.preventDefault();
            $('#submitButton').one('click', function(event) { submitClick(event); });
            $('#submitButton').removeClass('disabledButton');
         }
      });
      

      JQuery One 事件: http://api.jquery.com/one/

      【讨论】:

      • 太棒了!感谢您的信息,此行为将完成
      • 我尝试了 javascript 代码,但在 $(this).valid() 函数中出现错误。它表示对象 $(this) 没有 valid() 函数。
      【解决方案3】:

      为什么不直接使用:

      function disableButtons() {
          var form = $(this);
          var btns = $("input:submit", form);
      
          if (!form.valid()) {
              // allow user to correct validation errors and re-submit
              btns.removeAttr("disabled");
          } else {
              btns.attr("disabled", "disabled");
          }
      }
      

      禁用您的按钮并使用以下方法激活它:

      $("form").bind("submit", disableButtons);
      

      【讨论】:

      • 这是最通用的一个,它工作得很好..谢谢
      【解决方案4】:

      我有一个使用 MVC3 非侵入式验证的表单,以及一个带有 [RemoteAttribute] 的视图模型。 在我看来,表单的提交事件仅在所有验证通过后才会触发。我目前正在使用它,它似乎可以工作:

      <input type="submit" value="Submit the Form" 
          data-app-disable-on-submit="true" />
      
      $('form').live('submit', function() {
          $(this).find('input[type="submit"][data-app-disable-on-submit="true"]')
                      .attr('disabled', 'disabled');
      })
      

      ;

      我在远程属性验证操作方法和 HttpPost 操作方法上都设置了断点。第一次单击提交按钮会命中验证操作方法上的断点。此时,该按钮仍处于启用状态。我可以多次单击它,并且在恢复验证方法后,HttpPost 只被命中一次。当点击 HttpPost 时,提交按钮被禁用。

      更新

      没错,你就是亚历克斯。所以上面的更新版本应该是这样的:

      $('form').on('submit', function() {
          $(this).find('input[type="submit"][data-app-disable-on-submit="true"]')
                      .attr('disabled', 'disabled');
      })
      

      【讨论】:

      • .live 已被弃用,在这种特殊情况下被 .on.submit 取代。无论如何,它对我不起作用。
      【解决方案5】:

      基于Ryan P's popular answer,我创建了以下通用解决方案,该解决方案也适用于我的 ajax 表单。

      使用以下类装饰您的自定义提交按钮:

      <button type="button" class="one-click-submit-button">Submit</button>
      

      将以下内容添加到您的 javascript 文件中:

      function OneClickSubmitButton() {
          $('.one-click-submit-button').each(function () {
              var $theButton = $(this);
              var $theForm = $theButton.closest('form');
      
              //hide the button and submit the form
              function tieButtonToForm() {
                  $theButton.one('click', function () {
                      $theButton.hide();
                      $theForm.submit();
                  });
              }
      
              tieButtonToForm();
      
              // This handler will re-wire the event when the form is invalid.
              $theForm.submit(function (event) {
                  if (!$(this).valid()) {
                      $theButton.show();
                      event.preventDefault();
                      tieButtonToForm();
                  }
              });
          });
      }
      
      OneClickSubmitButton();
      

      由于这是一个 ajax 表单,我们希望在服务器验证失败时重新加载处理程序。

      function MyForm_OnSuccess() {
          if (true if your form passed validation logic) {
              //do something since your form submitted successfully
          } else { //validation failed on server
              OneClickSubmitButton(); //reinitialize the button logic
          }
      }
      

      显然,如果您没有 ajax 表单,您可以省略整个 OneClickSubmitButton 函数业务并直接运行 $('.one-click-submit-button').each(...

      【讨论】:

      • 真的需要$theForm.submit() 吗?表格无论如何都会提交。我在my answer 中删除了它,它似乎工作得很好。
      【解决方案6】:

      AlexRyan P 的答案扩展到可能缺少 jQuery 验证以及单个表单中存在多个提交按钮的情况。

      oneClickSubmitButton = function () {
          $('input[type=submit], button[type=submit], input[type=image]').each(function () {
              var $theButton = $(this);
              var $theForm = $theButton.closest('form');
      
              //hide the button and submit the form
              function tieButtonToForm() {
                  $theButton.one('click', function () {
                      $theButton.addClass('ui-state-disabled');
                  });
              }
      
              tieButtonToForm();
      
              $theForm.submit(function (event) {
                  // Only proceed for the clicked button
                  if (!$theButton.hasClass("ui-state-disabled"))
                      return;
      
                  // If jQuery Validation is not present or the form is valid, the form is valid
                  if (!$theForm.valid || $theForm.valid())
                      return;
      
                  // Re-wire the event
                  $theButton.removeClass('ui-state-disabled');
                  event.preventDefault();
                  tieButtonToForm();
              });
          });
      };
      

      【讨论】:

        【解决方案7】:
         $('form').submit(function () {
         $('input[type="submit"]', this).attr('disabled', 'disabled');
           });
        

        【讨论】:

        • 这个解决方案对我有用。根据当今的可访问性标准,您还可以考虑包括 .attr("aria-busy", "true");
        【解决方案8】:

        我对此使用了不同的方法。不是连接到按钮的单击事件,而是连接到表单的提交事件。就像防止多个同时提交表单的魅力一样。

        function initFormsToPreventSimultaneousSubmits(selector) {
            if (!selector) {
                selector = 'form'; // No selector supplied, apply to all forms on the page
            }
        
            // Make sure all forms that conform to selector are marked as not submitting
            $(selector).each(function()
            {
                var $form = $(this);
                $form.data('submitting', false);
            });
        
            // Attach to submit event of all forms that conform to selector
            $(selector).off('submit').on('submit', function (e) {
                var $form = $(this);
        
                if (!$form.valid || $form.valid()) { // Make sure to only process when the form is valid or jquery validation is not used
                    if ($form.data('submitting')) {
                        // form is already submitting. Classic case of double click on one of the submit buttons of the form. Stop the submit
                        e.preventDefault();
                        return false;
                    } else {
                        // All ok, mark the form as submitting and let the form perform the submit
                        $form.data('submitting', true);
                        return true;
                    }
                }
            });
        }
        

        在文档准备好时,我调用 initFormsToPreventSimultaneousSubmits() 来初始化页面上的所有表单。

        唯一要记住的是,当您使用 ajax 表单发布时,是在 AjaxOptions 设置的 OnComplete 事件上调用 initFormsToPreventSimultaneousSubmits('#formId')。因为否则表单在完成后仍将被标记为提交。当使用“正常”表单帖子时,这不是问题。

        【讨论】:

          【解决方案9】:

          我可以用几行代码解决一个类似的问题。如果您不想“提醒”用户他们双击并只是默默地忽略第二次点击,我更喜欢这个。

          我刚刚创建了一个全局 javascript 变量,当我的函数在关键部分执行时我切换了该变量。这可以防止后续函数调用重新执行相同的部分。

           var criticalSection = false;
          
           SomeOnClickEventFired = function () {
                if (!criticalSection)
                {
                      criticalSection = true;
                      //Ajax Time
                      criticalSection = false;
                }
           }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2012-04-24
            • 2011-09-11
            • 1970-01-01
            • 2011-05-14
            • 2023-04-07
            • 1970-01-01
            • 2014-10-01
            相关资源
            最近更新 更多