The problem here has nothing to do with synchronous or asynchronous code.
Yes, if your AJAX call is asynchronous then that would be a problem, because event delegation is synchronous and will not wait for your AJAX call to return. But your call is synchronous, since you set async: true
.
The real underlying problem here is time.
The HTTP request you are making -- even though it is synchronous since you set async: false
-- takes time to complete, and by the time it has completed, the event delegation of the browser has already happened, thus your event.stopImmediatePropagation()
has no effect.
Ideally, you need to move your event.stopImmediatePropagation
to another spot, like so:
$(document).on('click', '[data-submit-form]', function (event) {
var form = $(this).closest('form');
event.stopImmediatePropagation(); // Do it here
$.ajax({
url : form.attr('action'),
type : 'post',
data: form.serialize(),
async: false,
success: function (data) {
if ($.type(data) === 'object') {
alert_errors(form, data);
// event.stopImmediatePropagation() NOT here
}
}
});
});
EDIT
Your current approach is not the most ideal way to do what you are trying to do, because your modal close and form submit logic are too tightly coupled since they're in the same click event.
Instead of having a submit form click event that also closes the modal, you should make the process slightly more granular with separate functions:
- One to handle the click event of the button and submit the form
- One to close the modal, which can be called from anywhere
With this approach, your code can stay as is and you call the closeModal function inside the success callback, like so:
// By default, this will NOT close the modal anymore. You must explicitly
// call 'closeModal' where you want, e.g. in the AJAX success callback.
// This type of granularity will be much more flexible and save you headache.
$(document).on('click', '[data-submit-form]', function (event) {
var form = $(this).closest('form');
$.ajax({
url : form.attr('action'),
type : 'post',
data: form.serialize(),
async: false,
success: function (data) {
if ($.type(data) === 'object') {
alert_errors(form, data);
closeModal(); // Close modal
}
}
});
});
An approach like this is much cleaner because as your functionality grows and grows, you're going to keep finding yourself with more and more weird scenarios in which you want to call preventDeafult
, stopPropagation
, stopImmediatePropagation
, and so on, and I guarantee you will run into this same problem again as a result. It will just be a mess.
Save yourself the hassle now.