Disable the form and all contained elements until the ajax request completes (or another solution to prevent multiple remote requests)

I have a search form with inputs and choices, and when some input / selection is changed, I run some js and then create an ajax request with jquery. I want the user not to make further changes to the form during the execution of the request, since at the moment they can initiate several remote searches at the same time, which actually causes a race between different searches.

It seems like the best solution is to prevent the user from interacting with the form while waiting for the request. At the moment, I am doing this in the most severe way, hiding the form before making an ajax request, and then showing it again about success / error. This solves the problem, but it looks awful and not very acceptable. Is there another, better way to prevent interaction with the form? To make things more complex, to allow beautiful choices, the user actually interacts with the gaps that js are connected to them to relate to the actual, hidden choices. Thus, although the gaps are not inputs, they are contained in the form and are real interactive form elements.

Grateful for any advice - max. Here is what I am doing now:

function submitQuestionSearchForm(){ //bunch of irrelevant stuff var questionSearchForm = jQuery("#searchForm"); questionSearchForm.addClass("searching"); jQuery.ajax({ async: true, data: jQuery.param(questionSearchForm.serializeArray()), dataType: 'script', type: 'get', url: "/questions", success: function(msg){ //more irrelevant stuff questionSearchForm.removeClass("searching"); }, error: function(msg){ questionSearchForm.removeClass("searching"); } }); return true; } 

where the search class now only has {display: none}

+4
source share
5 answers

I use this plugin http://jquery.malsup.com/block/ , it implements a translucent img that can be applied to a Div or a full page, it is pretty good and cross-browser supported.

EDIT: Since some people have stated that this plugin does not block the input of the form, selects, etc. If you really want this to be bulletproof and not allow people to bother with the form necessary for further blocking, I suggest using a clean HTML solution something like this fooobar.com/questions/79159 / ...

+5
source

You can display a div that takes up the entire page space when an AJAX request is run (you can put the loading background in the middle and make it transparent) and hide it when that is done.

I think that you can also make synchronous calls non-asynchronous, I think that it will β€œblock” the navigator until the request is completed.

0
source

How to use a boolean value to prevent multiple AJAX requests from starting? You can also use boolean elements to disable / enable.

Something like the following (see comments on my additions):

 // set initial boolean state var isRequestFinished = true; function submitQuestionSearchForm(){ // check if previous request has finished if(isRequestFinished){ // request just started, so set boolean to false isRequestFinished = false; jQuery.ajax({ async: true, data: jQuery.param(questionSearchForm.serializeArray()), dataType: 'script', type: 'get', url: "/questions", success: function(msg){ questionSearchForm.removeClass("searching"); // request just finished, so set boolean to true isRequestFinished = true; }, error: function(msg){ questionSearchForm.removeClass("searching"); } }); } return true; }; 

I have not tested this code, but it should point you in the right direction. Before you call jQuery.ajax() , you can turn off all the elements you want, and then turn them back on in the callback.

0
source

I really decided to solve this problem in a different way, as I expected: instead of stopping interacting with the form, I instead start a new ajax request and abort any previous ones. Thus, the server still receives many requests, but I ignore the answer for all but the most recent.

Here's how I set the form to make this happen (I added a lot of spaces to make it clearer):

 <form onsubmit="if(typeof(remoteSearch) != "undefined"){ remoteSearch.abort(); } remoteSearch = jQuery.ajax({ async:true, data:jQuery.param(jQuery(this).serializeArray()), dataType:'script', type:'get', url:'/my-search-url' }); return false;" method="get" action="/my-search-url" > 

There is no success block here, because I have a separate handler for processing the results of the ajax call, but you can add it.

0
source

None of the published solutions take into account keyboard interactions.

You can simply add the disabled attribute to your submit button when sending (and remove it when the server responds). But you can still send text focus using the keyboard. (adding disabled is still a good UX)

A more robust solution to preventing user interaction with the form is to prevent events from ever reaching the elements.

A quick and dirty test shows that only preventDefault() events are keydown , click , dragstart and drop . Also for mobile devices, we need to blur() any input element that focuses (only for Android testing).

Here is a brief example (the last two methods are its essence):

 const form = document.querySelector('form') const status = document.querySelector('.status') const showStatus = s=>status.textContent=s||'' const events = ['keydown','click','dragstart','drop','focus'] form.addEventListener('submit',e=>{ e.preventDefault() lockForm(form,true) showStatus('submitting') setTimeout(fakeResponse,10000) }) function fakeResponse(){ lockForm(form,false) showStatus() } function lockForm(form,lock){ lock ?events.forEach(event=>form.addEventListener(event,preventDefault,false)) :events.forEach(event=>form.removeEventListener(event,preventDefault,false)) } function preventDefault(e){ e.target.blur() e.preventDefault() } 
 body { font-family: Arial, sans; line-height: 100%; } label { display: block; margin-bottom: 10px; box-shadow: 0 -1px 0 0 #EEE inset; } label:after { content: ''; display: table; clear: both; } input, textarea { width: 50%; float: right; } .status { margin-top: 20px; line-height: 200%; text-align: center; background-color: #FF0; } 
 <form method="GET" action="https://httpbin.org/get"> <h3>form disables while submitting by stopping events</h3> <label>text<input></label> <label>text disabled<input disabled></label> <label>textarea<textarea></textarea></label> <label>textarea disabled<textarea disabled></textarea></label> <label>checkbox<input type="checkbox"></label> <label>checkbox disabled<input type="checkbox" disabled></label> <button type="submit">submit</button> </form> <div class="status"></div> <h3>elements outside the form still function normally</h3> <label>text<input></label> 
0
source

Source: https://habr.com/ru/post/1310528/


All Articles