RAILS 6 Ajax events and Ajax Spinner

Viewed 711

I am trying to show a loading animation / spinner on every Ajax request

my application.js

$(document).on("turbolinks:load", function() {
  window.addAjaxLoaderHandler();
});

window.addAjaxLoaderHandler = function() {
  $(document).on('ajax:send', function() {
    $('#ajax-loader').show();
  });

  $(document).on('ajax:complete', function(){
    setTimeout(() => {$('#ajax-loader').hide();}, 100);
  });
}

This works perfectly, UNTIL I load a remote form by AJAX. If I submit that newly loaded form the ajax:send fires, but after completion (without any errors) the ajax:complete does not (the spinner will not be hidden).

The problem seems to be that I remove the loaded form with the ajax call.

What can I do to make this work?

I am just trying to click a link, load a form and remove the form after sending its information.

UPDATE

My application.html.haml (I use HAML so syntax is accordingly, so #... means <div id="...">#all indented code lines#</div>)

#main
  = yield

#ajax-loader

The form will be loaded like:

$('#main').append('<%= j(render(:partial => 'new', :locals => {:model => @model})) %>');

The problem is that #ajax-loader is not hidden and still shows after form is submitted.

I think the problem is, that I remove the AJAX-call triggering element. But I was hoping, that since I bound the listener to document, that it still triggers.

Of course in this case I just can do $('#ajax-loader').hide();, but I am trying to understand why ajax:complete is not fired.

1 Answers

I guess you answered your own question: the problem is that when you remove the form, so does the event listener.

You can check what event listeners still apply to your document object using getEventListeners(document). Try this on your console* after the spinner is fired and refuses to hide.

*edit: this is a Google Chrome function, might not work in other browsers, though most of them have ways to inspect the listeners on a node

I think of these workarounds:

a) Rebinding the listeners everytime you remove a form;

b) Attaching the listener to the window object instead of document

c) If you are using jQuery Ajax you could use the beforeSend and complete properties to show and hide the spinner instead of events. If it's not jQuery Ajax there's probably a similar way to achieve the same behavior.

Related