在多个ajax调用完成之前,如何阻止表单提交? jQuery的

时间:2022-08-23 18:00:36

Following on from a previous question where I asked about disabling a submit button until all ajax calls have finished returning...

继上一个问题后,我询问了关于禁用提交按钮,直到所有ajax调用都完成返回...

It seems that people are still managing to submit the form even with the button disabled and a warning sign. I guess it could be from pressing 'enter' in a text input.

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

How do I go about disabling the whole form, rather than just the submit button?

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

The code so far is:

到目前为止的代码是:

// 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);
});

One other thing that I should mention which could be causing a problem is that there are multiple ajax calls happening at the same time, EG one div receives hidden inputs and another div elsewhere on the page shows a price total for instance.

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

Would the fact that some ajax calls are completing quickly negate the disabling effect of ajaxStart? EG ajax call1 and ajax call2 both fire the ajaxStart - call1 finishes really quickly, would it re-enable the form while we are waiting for call2 to complete?

一些ajax调用快速完成的事实是否会否定ajaxStart的禁用效果? EG ajax call1和ajax call2都触发了ajaxStart - call1很快就完成了,它会在我们等待call2完成时重新启用表单吗?

Is there a better way of doing this where we could simply test if ALL ajax calls have completed?

有没有更好的方法来做到这一点我们可以简单地测试所有ajax调用是否已经完成?

5 个解决方案

#1


2  

You can add an event handler for the submit event of the form. The event handler can check if the submit is allowable yet, and abort if not. Here's some docs: http://api.jquery.com/submit/

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

Note that if javascript on the page calls .click() on one of the form submission buttons, the form will be submitted without calling your .submit() handler. This is a weird jQuery issue (http://groups.google.com/group/jquery-en/browse_thread/thread/1317bfd4e3a8b233?pli=1) which I guess the jQuery folks don't consider a bug. There may be other cases like this, I hope not.

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

If you're using ASP.NET, depending on whats on the form, ASP.NET may inject a "__doPostBack" function. You may need to hook that function instead by redefining it with some custom code that calls the original.

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

#2


1  

You could just set a JS object with multiple properties for each ajax call. Example:

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

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

On form submit loop through each property to check for true. If any are false do not submit the form.

在表单提交循环通过每个属性检查是否为true。如果有任何不对,请不要提交表格。

As each ajax call completes set its property (call1, call2, etc) to true.

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

Thats one way you could do it, whether its the best way, I don't know.

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

#3


0  

How about creating a global variable:

如何创建全局变量:

  var i = 0;

and each AJAX call increments this variable at the start of the call and decrements it when complete.

并且每个AJAX调用在调用开始时递增此变量,并在完成时递减它。

On submit of the form, check if this variable is greater than 0 and prevent the submit.

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

  function submitForm(){
      return i == 0;
  }

<form onsubmit="submitForm()"....>

</form>

#4


0  

I guess you have some code like this:

我想你有一些像这样的代码:

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

you can do that:

你可以这样做:

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


0  

I've nearly solved this but somehow people seem to still be able to submit the form before the callbacks have finished.

我几乎已经解决了这个问题但是人们似乎仍然可以在回调完成之前提交表单。

I don't know if it's coincidence but all the people who have managed to submit it have been using Safari on Mac.

我不知道这是不是巧合,但所有设法提交它的人都在Mac上使用Safari。

Here's the method I am using, would be great if anyone could spot the flaw in the logic.

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

Using Vincent's suggestion:

使用文森特的建议:

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

then when I do an ajax call for instance:

然后当我做一个ajax调用时:

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

This is working fine, I also have a nice little script to give user feedback - button is greyed out while waiting for ajaxcounters to return and if it takes longer than 250ms, an animation is displayed too. Once all ajax calls have completed, the counter is back to zero and the button is displayed as normal:

这工作正常,我还有一个很好的小脚本来提供用户反馈 - 按钮在等待ajaxcounters返回时显示为灰色,如果它需要超过250ms,则也会显示动画。完成所有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);
    }
});

Finally, we come to the function which should prevent submission, but doesn't seem to be working:

最后,我们来到了应该阻止提交的功能,但似乎没有起作用:

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

Can anybody spot what I have done wrong here?

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

Thanks!

谢谢!

#1


2  

You can add an event handler for the submit event of the form. The event handler can check if the submit is allowable yet, and abort if not. Here's some docs: http://api.jquery.com/submit/

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

Note that if javascript on the page calls .click() on one of the form submission buttons, the form will be submitted without calling your .submit() handler. This is a weird jQuery issue (http://groups.google.com/group/jquery-en/browse_thread/thread/1317bfd4e3a8b233?pli=1) which I guess the jQuery folks don't consider a bug. There may be other cases like this, I hope not.

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

If you're using ASP.NET, depending on whats on the form, ASP.NET may inject a "__doPostBack" function. You may need to hook that function instead by redefining it with some custom code that calls the original.

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

#2


1  

You could just set a JS object with multiple properties for each ajax call. Example:

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

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

On form submit loop through each property to check for true. If any are false do not submit the form.

在表单提交循环通过每个属性检查是否为true。如果有任何不对,请不要提交表格。

As each ajax call completes set its property (call1, call2, etc) to true.

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

Thats one way you could do it, whether its the best way, I don't know.

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

#3


0  

How about creating a global variable:

如何创建全局变量:

  var i = 0;

and each AJAX call increments this variable at the start of the call and decrements it when complete.

并且每个AJAX调用在调用开始时递增此变量,并在完成时递减它。

On submit of the form, check if this variable is greater than 0 and prevent the submit.

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

  function submitForm(){
      return i == 0;
  }

<form onsubmit="submitForm()"....>

</form>

#4


0  

I guess you have some code like this:

我想你有一些像这样的代码:

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

you can do that:

你可以这样做:

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


0  

I've nearly solved this but somehow people seem to still be able to submit the form before the callbacks have finished.

我几乎已经解决了这个问题但是人们似乎仍然可以在回调完成之前提交表单。

I don't know if it's coincidence but all the people who have managed to submit it have been using Safari on Mac.

我不知道这是不是巧合,但所有设法提交它的人都在Mac上使用Safari。

Here's the method I am using, would be great if anyone could spot the flaw in the logic.

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

Using Vincent's suggestion:

使用文森特的建议:

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

then when I do an ajax call for instance:

然后当我做一个ajax调用时:

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

This is working fine, I also have a nice little script to give user feedback - button is greyed out while waiting for ajaxcounters to return and if it takes longer than 250ms, an animation is displayed too. Once all ajax calls have completed, the counter is back to zero and the button is displayed as normal:

这工作正常,我还有一个很好的小脚本来提供用户反馈 - 按钮在等待ajaxcounters返回时显示为灰色,如果它需要超过250ms,则也会显示动画。完成所有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);
    }
});

Finally, we come to the function which should prevent submission, but doesn't seem to be working:

最后,我们来到了应该阻止提交的功能,但似乎没有起作用:

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

Can anybody spot what I have done wrong here?

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

Thanks!

谢谢!