0

I'm using JavaScript and jQuery to write a handler for my form being submitted. Based on certain conditions, the handler may allow or prevent the form from submitting.

This is straight forward but is made more complex by the fact that the handler needs to make an AJAX call.

The issue is that my handler will return right away with true or false, but I won't get the response from the AJAX call until later. But I need the result from the AJAX call to decide what the return value should be.

Seems like this must surely be a common scenario. Are there best practices for handling this case?

Jonathan Wood
  • 65,341
  • 71
  • 269
  • 466
  • So you want to allow/deny the default functionality based on the information you received from the ajax call? Async/Await could be the way to go here – clash Feb 07 '22 at 18:30
  • @clash: Yes, that's correct. – Jonathan Wood Feb 07 '22 at 18:30
  • So this could help? https://stackoverflow.com/questions/48506445/how-to-return-an-ajax-result-using-async-await – clash Feb 07 '22 at 18:32
  • @clash: Not sure how that would be incorporated with an AJAX call. – Jonathan Wood Feb 07 '22 at 18:33
  • Either: 1) don't post the form using submit, and instead `$.post` it (ie in code, in the ajax success callback). 2) handle jquery submit and e.preventDefault() then call your ajax and in the success callback, call `$("form")[0].submit()` which will call the DOM submit rather than the (now blocked) jquery submit. – freedomn-m Feb 07 '22 at 18:34
  • @freedomn-m: Yes, that makes sense. – Jonathan Wood Feb 07 '22 at 18:36
  • $.get used in this question is just a shortcur $.ajax({ method:'GET'}), so just "await $.ajax(..your call..)". Here a quickly searched article: https://petetasker.com/using-async-await-jquerys-ajax. – clash Feb 07 '22 at 18:36
  • @clash who mentioned $.get? – freedomn-m Feb 07 '22 at 18:36
  • @freedomn-m https://stackoverflow.com/questions/48506445/how-to-return-an-ajax-result-using-async-await Preventing by default and acting after the ajax call finished can be valid solution as well. – clash Feb 07 '22 at 18:37
  • Ah - in *that* question, not *this* question, got it. Wasn't clear with 3 comments inbetween. And $.get is shorthand for $.ajax, so you could do `await $.get` – freedomn-m Feb 07 '22 at 18:38
  • @clash: Interesting. I'm primarily a C# developer. Didn't realize there was an await for AJAX calls. – Jonathan Wood Feb 07 '22 at 18:38
  • Yea sorry was a followup on my comment above, should have edited it I guess. Both solutions came to my mind, I think I would prefer async/await since you would need to "implement" the default behavior by yourself. Would be a little overhead. – clash Feb 07 '22 at 18:41

1 Answers1

0

My answer on basis what was discussed shortly in the comments, there are (at least) two possible solutions.

  1. Async/await:

Wait for the ajax call to finish and prevent default behavior based on the response. (await $.ajax / await $.post/get)

  1. Prevent by default (as mentioned by @freedomn-m)

You could prevent the default behavior always, wait for the ajax call to finish and execute the desired behavior afterwards. For example with withholding a form submit.

e.preventDefault();
$ajax...
...
...
if (should_not_be_prevented) {
  $("#myForm").submit()
}
clash
  • 427
  • 4
  • 11
  • That's not actually my suggestion :) – freedomn-m Feb 07 '22 at 18:49
  • `$("form").submit(function() { e.preventDefault(); $.ajax(...).done(function(data) { if (data.isOk) $("form")[0].submit() }) });` note 2 items: code in `.done` and `$("form")[0]` to select the DOM submit. – freedomn-m Feb 07 '22 at 18:50
  • It's not working like I expected. I couldn't find an example for using an async function with `$('...').on('click', function () { ... })`. And when I try stepping through the code the code that comes after runs immediately when I try to step over the AJAX call. So it isn't allowing the code to test the return value. – Jonathan Wood Feb 07 '22 at 19:17
  • how about using an async function as callback? $('..').on('click', async () => {}); – clash Feb 08 '22 at 13:00
  • @freedomn-m maybe not your suggestion, but you mentioned it ;) – clash Feb 08 '22 at 13:02