jquery button registers multiple clicks instantly

I have a button in my form that is intended to check whether or not the authorization information has been entered correctly. It does this by firing off an ajax call to a controller in my Ruby on Rails application and checking the result. The problem is that even when I click the button only once, it immediately registers multiple clicks - sometimes as many as 5! - and fires that ajax call multiple times, which hits the API I'm checking multiple times as well. Here is what I have in my html.erb file:
<%- content_for :js do -%>
<%= javascript_tag nonce: true do -%>
$( document ).on('turbolinks:load', function() {
var $form = $("form");
var $buttons = $('#soap-access, #rest-access, #email-access, #audview-access', $form);
var $jobSchedule = $('#client_job_schedule', $form);
$buttons.click(function (e) {
var $button = $(this);
$button.prop('disabled', true);
var $parent = $button.parent();
var $spinner = $('.fa-sign-in', $parent);
var $signIn = $('.fa-spinner', $parent);
var $success = $('.fa-check', $parent);
var $error = $('.fa-times', $parent);
var data = {};
var $endpoint = '';
// add stuff to data
$signIn.toggleClass('d-none');
$spinner.toggleClass('d-none');
$success.addClass('d-none');
$error.addClass('d-none');
$.ajax({
type: "GET",
url: "<%= api_authentication_clients_path %>",
data: data
})
.done(function () {
$success.removeClass('d-none');
})
.fail(function (jqXHR) {
$error.removeClass('d-none');
if (jqXHR.responseJSON && jqXHR.responseJSON.message) {
alert(jqXHR.responseJSON.message);
} else {
alert('Error trying to authenticate');
}
})
.always(function () {
$button.prop('disabled', false);
$spinner.toggleClass('d-none');
$signIn.toggleClass('d-none');
});
});
});
<% end -%>
<% end %>
You can see that I add the 'disabled' prop very first thing, and remove it at the end.
I also tried taking out the removal of the disabled prop at the end just in case it was somehow getting re-enabled immediately. The button is indeed visually disabled, but the extra clicks have already been registered and all the ajax calls still happen, one after another.
I've also tried things like e.stopImmediatePropagation();
and e.preventDefault();
to no avail.
Answer
After you define jobSchedule, add this at the next line:
$buttons.off('click');
That will unbind any previous clicker handlers.
After that:
$buttons.on('click', function (e) {
e.preventDefault();
// check at the beginning of click handler
// to make sure button isn't already disabled
if ($(this).prop('disabled')) {
return;
}
// rest of your code..
var $button = $(this);
$button.prop('disabled', true);
var $parent = $button.parent();
});
});
This should stop multiple click registrations by making sure each button has only one clicker handler no matter how many times Turbolinks events fired.
Enjoyed this article?
Check out more content on our blog or follow us on social media.
Browse more articles