【问题标题】:How do I prevent form submission until multiple ajax calls have finished? jquery在多个 ajax 调用完成之前,如何防止表单提交? jQuery
【发布时间】:2011-01-18 10:08:25
【问题描述】:

从 previous question 开始,我询问是否禁用提交按钮,直到所有 ajax 调用都完成返回...

即使按钮被禁用并带有警告标志,人们似乎仍在设法提交表单。我想这可能是在文本输入中按“输入”。

如何禁用整个表单,而不仅仅是提交按钮?

目前的代码是:

// if we're waiting for any ajax to complete we need to disable the submit
$(document).ajaxStart(function() {
  $(".ajaxbutton").attr("disabled", "disabled");
  // if it's taken longer than 250ms display waiting message
  timer = setTimeout(function() {
    $('#processingAlert').html(' ...please wait one moment');
    $('#processingAlert').show();
  }, 250);
})
$(document).ajaxComplete(function() {
  $(".ajaxbutton").removeAttr("disabled");
    $('#processingAlert').hide();
    // cancel showing the message when the ajax call completes.
clearTimeout(timer);
});

我应该提到的另一件事可能导致问题是同时发生多个 ajax 调用,例如,一个 div 接收隐藏的输入,而页面上其他地方的另一个 div 显示总价格。

一些 ajax 调用正在快速完成这一事实是否会抵消 ajaxStart 的禁用效果? EG ajax call1 和 ajax call2 都触发 ajaxStart - call1 完成得非常快,它会在我们等待 call2 完成时重新启用表单吗?

有没有更好的方法来测试是否所有 ajax 调用都已完成?

【问题讨论】:

    标签: jquery ajax validation forms


    【解决方案1】:

    您可以为表单的提交事件添加事件处理程序。事件处理程序可以检查提交是否允许,如果不允许则中止。这是一些文档:http://api.jquery.com/submit/

    请注意,如果页面上的 javascript 在其中一个表单提交按钮上调用 .click(),则将在不调用您的 .submit() 处理程序的情况下提交表单。这是一个奇怪的 jQuery 问题 (http://groups.google.com/group/jquery-en/browse_thread/thread/1317bfd4e3a8b233?pli=1),我猜 jQuery 的人不认为这是一个错误。可能还有其他类似的情况,我希望不会。

    如果您使用的是 ASP.NET,根据表单上的内容,ASP.NET 可能会注入“__doPostBack”函数。您可能需要通过使用一些调用原始代码的自定义代码重新定义该函数来挂钩该函数。

    【讨论】:

    • 这听起来很正确,来自手册: $("form").submit(function() { if ($("input:first").val() == "correct ") { $("span").text("Validated...").show(); return true; } $("span").text("无效!").show().fadeOut( 1000); 返回假; });因此,如果我检查所有 ajax 调用是否已完成,我可以返回 true。我用的是 PHP,所以很遗憾不能使用 ASP 函数。
    • PS 谁能告诉我如何在评论中插入格式化的代码,我似乎总是把所有东西都挤在一行上
    • 我认为您不能在 cmets 中格式化代码。我会继续用其他 cmets 扩展您的问题。
    【解决方案2】:

    您可以为每个 ajax 调用设置一个具有多个属性的 JS 对象。示例:

    var requiredCalls = {call1: false, call2: false, call3: false}
    

    在表单提交时循环遍历每个属性以检查是否为真。如果有任何错误,请不要提交表单。

    当每个 ajax 调用完成时,将其属性(call1、call2 等)设置为 true。

    这是你可以做到的一种方式,我不知道它是否是最好的方式。

    【讨论】:

    • 这听起来是个好主意,但是可以在此页面上进行多个不同的调用,并非所有调用都是由每个客户触发的。我会考虑的。
    • 在这种情况下,如果我理解正确,您可以将它们的默认值设置为 true。当触发 ajax 调用时,您将在 requiredCalls 中将其属性设置为 false 并在 oncomplete/onsuccess 中将其设置回 true。
    【解决方案3】:

    创建一个全局变量怎么样:

      var i = 0;
    

    并且每次 AJAX 调用都会在调用开始时递增该变量,并在调用完成时递减它。

    在提交表单时,检查该变量是否大于0并阻止提交。

      function submitForm(){
          return i == 0;
      }
    
    <form onsubmit="submitForm()"....>
    
    </form>
    

    【讨论】:

    • 这听起来很通用。在 ajax 调用中的哪个点我们增加/减少。是在 $.ajax({
    • 我想你在 ajaxStart 函数开始时递增,在 ajaxComplete 函数开始时递减
    • 这似乎是个好主意,但是当我尝试时,所有 3 个 ajax 调用同时开始,计数器的值为 1。然后当它们在不同时间完成时,计数器变为 -2 .
    【解决方案4】:

    我猜你有这样的代码:

    var form = $(...);
    form.bind ('submit', function (...) {
      $.ajax (
        ...,
        complete: function (...) {
          // do something
        }
      );
    }
    

    你可以这样做:

    var form = $(...);
    form.bind ('submit', function (...) {
      if ($ (this).data ('inprogress') === null) {
        $ (this).data ('inprogress', 1);
        // disable submit button
        $.ajax (
          ...,
          complete: function (...) {
            // do something
            $ (this).data ('inprogress', null)
            // enable submit button
          }
        );
      } else {
        // display notification / warning
      }
    }
    

    【讨论】:

      【解决方案5】:

      我几乎解决了这个问题,但不知何故,人们似乎仍然能够在回调完成之前提交表单。

      我不知道是不是巧合,但所有成功提交的人都在 Mac 上使用过 Safari。

      这是我正在使用的方法,如果有人能发现逻辑中的缺陷,那就太好了。

      使用文森特的建议:

      // set this to zero before any ajax calls are made  
      var ajaxcallcounter = 0;
      

      然后当我进行 ajax 调用时:

          // UPDATE SHIPPING BOXES
          var data = 'pickup=1';
          ajaxcallcounter++;
          $.ajax({
          type: "POST",
          url: "incViewbasketShippingBoxes.php", 
          data: data,
          success: function(response) {
              $('#shippingBoxes').html(response);
                  ajaxcallcounter--;
          }
          });
      

      这工作正常,我还有一个不错的小脚本来给用户反馈 - 在等待 ajaxcounters 返回时按钮是灰色的,如果它花费的时间超过 250 毫秒,也会显示动画。一旦所有的 ajax 调用都完成,计数器就会归零,并且按钮会正常显示:

      // when ajaxStart is triggered, keep an eye on the ajaxcallcounter
      $(document).ajaxStart(function() {
        $(".ajaxbutton").attr("disabled", "disabled");
        $('#processingAlert').html(' ...calculating');
        $('#processingAlert').show();
      
        // if it's taken longer than 250ms (say) display waiting message
        timer = setTimeout(function() {
          $('#processingAlert').html(' ...calculating <img src="../gfx-site/ajax-loader.gif">');
        }, 250);
      });
      // when ajaxComplete is triggered, keep an eye on the ajaxcallcounter
      $(document).ajaxComplete(function() {
          if (ajaxcallcounter == 0) {
              $(".ajaxbutton").removeAttr("disabled");
              $('#processingAlert').hide();
              // cancel showing the message when the ajax call completes.
          clearTimeout(timer);
          }
      });
      

      最后,我们来看看应该阻止提交但似乎不起作用的功能:

      // can we submit yet?
        $('#checkoutform').submit(function() {
          if (ajaxcallcounter == 0) {
            return true;
          }
          return false;
        });
      

      谁能发现我在这里做错了什么?

      谢谢!

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-04-19
        • 1970-01-01
        • 2013-04-13
        相关资源
        最近更新 更多