Skip to main content

Button Loading Animations with jQuery UJS Discussion

General • Asked by Chris Oliver
Innokenty Longway

Thank you! Really simple. :)

Works also with button_to, but to invoke font awesome [... remove needles spaces in what follows ...] data: {disable_with: raw(" < i class='fa fa-spinner fa-spin'> < /i>One moment please...")}

I just fixed the example code in the notes. It was getting automatically removed on accident.

Nice tutorial... as always :'D

I have a little problem here!
As you can see on my screenshot (, the spin doesn't show itself... And I don't know why...

Here is my code :

<%= f.button "Sign in", class: "btn btn-primary", data: { disable_with: " Connexion en cours..." } %>

I see "Connexion en cours..." but not the spin

I have install font-awesome-rails (gem 'font-awesome-rails', '~>')

Thanks for your help!

1. Make sure font-awesome is included in your application.css
2. If you put the font-awesome icon on the page outside of the button, does it show up by itself?

I have this on my application.css.scss :

@import "bootstrap";
@import "font-awesome";

I found a strange bug... by testing point 2. ^^'

When I add this on my <h2> it works (on my h2 and on my loader)
<h2>Sign in</h2>
But when I remove it, it disappears on both... WHAT THAT'S CRAZY!

Here the screenshots :

with h2 spinner :
without h2 spinner :

This post was just in time. I was looking for a dead-simple submit feedback animation. Perfect. :)

Chris, thank you so much for this! I've been struggling getting fontawesome to work with my buttons. Perfect timing. Your videos rock!

Thank for this nice tip :)

Anyway, how can i acheive this with haml and inside link_to?? I try with:

= button_to "Go Rails!".html_safe, akcept_path, method: :patch, class: 'btn btn-success', data: { disable_with: " Waiting..." in my label instead <button class..="" thx="">

You might just be missing the ending curly brace. This works for me:

= button_to "Go Rails!".html_safe, events_path, method: :patch, class: 'btn btn-success', data: { disable_with: " Waiting..."}

Fantastic stuff. Thanks for your efforts.

Having a bit of a problem with this. The disable action works, but the icon never shows up. However, if I have the icon already spinning somewhere else on the page first, the icon does show up when I click the button. What gives? Is it not loading fontawesome because there's none of the font there at page load?

That's interesting. Do you get any errors in the console that show the browser having trouble loading the icon font by chance?

I was getting the basically the same behaviour as James M. I checked the console and there were no error messages.

Seems to be some caching problem with font-awesome. I changed to a css only spinner e.g. This worked find and I could get rid of the font-awesome dependency. Thank you for a useful tutorial.

Did you get anywhere with this? Im getting the same issue in Chrome, but its working fine in Firefox.

In Safari i'm also getting no Icon and additionally the text fails to change as well.

I figured this out, at least for my situation. Once the font is loaded into the cache, I no longer have an issue with the spinner not showing up. If it is not loaded, the spinner eventually shows up where it needs to be if the form submit time is long enough. Is there a way to force a pre-load of the font? In the absence of a workaround, it seems like it might make more sense to just use a small image instead of having to load a whole font...

EDIT: I see no difference in behavior between chrome and firefox.
EDIT2: I'm using Rails 4.1.5 if that matters

Yes, this doesn't work in Safari.  Even this page does not in Safari.

Christoper Drane's solution above is an awesome supplement to Chris' tutorial. I had the same issue - font awesome was not working until after the spinner was cached. I switched to a pure CSS solution per using relative positioning and on a div itself instead of the before pseudo element. Much faster, no hiccups, and works everywhere!

Does this only work with a submit button? ie it won't work with type: "button" ?

Did you ever figure this out? I'm also not having success with a button that has the 'button' type

You won't use it with <input> at all because neither <input type="submit"> nor <input type="button"> allow for HTML inside of it. You'll have to use the <button></button> tag to use this.

I am using <button>. Here is the HTML:

<button class="btn btn-primary" data-disable-with="Checking..." data-discount-submit="1" id="job-code-button" type="button">Apply</button>

Hmm. I've got this on the login page here on GoRails:

<button class="btn btn-success btn-lg btn-block" data-disable-with="&lt;i class='fa fa-spinner fa-spin'&gt;&lt;/i&gt; Signing in..." name="button" type="submit">Sign in</button>

Only other thing I can think of is maybe your jquery-ujs isn't being loaded successfully and so it never gets triggered on click.

Note yours does have type = "submit" whereas @Marklar and I were wondering about buttons with type="button". Do you think that could be the problem? The top 3 lines of my application.js look like this:

//= require jquery
//= require jquery_ujs
//= require jquery-1.11.0.min.js

It looks like when I change it to type="button" the form does not submit which means the JS won't fire either.

Ahh maybe that's it. My use case is not technically a form. I have a box for entering a promo code within my form but I couldn't make it a form-within-a-form because the submit button would submit the main form. I just have an input with a button that is being listened to for a click event that generates an Ajax request that validates the input. Would that be the problem?

Oh I bet that's the case. I would guess that the jquery-ujs script listens to the form's submit event and since you aren't firing it, it won't happen.

It seems you could probably call the jquery-ujs methods to disable the elements in your callback.

Sorry if this is a little late but this is how I implemented a button without being type submit:

<%= button_tag "Save", data: {disable_with: " Signing in..."}, :id => "submit-document-button", class: "btn btn-success", type: "button" %>

I copied the exact same code but the UJS still isn't working for me. Here is the HTML:

<button class="btn btn-lg btn-success pull-right" data-disable-with="Processing..." id="finish-and-pay-button" name="button" type="button">Finish and Pay</button>


I think I finally found a solution that works for my use case. It involves using a link with remote: true and disable_with on the data option. It looks like this:

= link_to "Finish and Pay", pay_job_path(@job), method: :post, id: 'finish-and-pay-button', class: "btn btn-lg btn-success pull-right", remote: true, data: {disable_with: "Processing..."}

Great tutorial! Just curious how I could implement this using the 'Font-Awesome-Sass' gem? I tried it, but it's throwing an error because of it having an ERB tag within an ERB tag.

What's your code look like?

<%= f.button 'Log in', class: 'btn btn-success', data: { disable_with: "<%= icon('spinner') %> Logging In..." } %>

You can accomplish that using string interpolation here because it's Ruby code inside the ERB tag.

<%= f.button 'Log in', class: 'btn btn-success', data: { disable_with: "#{icon('spinner')} Logging In..." } %>

Doing that does fix the error, but it doesn't show the icon.

You'll have to make sure your assets are loaded properly and the icons display elsewhere.

Sometimes it won't display right away because your icon font isn't loaded until you click the button and it takes too long to load.

NAILED IT! Thanks Chris!

if using font-awesome-rails you might wanna use fa-icon('spinner').
icon('spinner') didn't work for me.

Great tutorial @chris! :)

Yup! The libraries have a couple different helper methods. I got confused using the wrong gem the other day. ;)

Ok a question here, I used what you taught on a form and it worked perfectly. Now I tried using it on a form that has multiple file fields and it didnt work... using carrierwave.. would there be a specific reason why that wouldnt work?

Paste a Github gist of your code and the HTML it generates and I'll take a look for ya!

How can we use with f.submit tag

Unfortunately you can't because it doesn't allow HTML inside of it.

This is great. Thanks for the great videos as usual. When using a button that is rending info through ajax, how do you enable the original button? My fa-icon jus keeps spinning. My code: <%= link_to 'Stats', course_heat_map_path(@course, lesson), remote: true, class: 'expandable tiny label', data: {disable_with: " Calculating Stats..."} %> and it is grabbing data from a .js.erb page and rendering it. Thanks in advance

You can use Rails UJS directly to do that. I use this and the @form variable is just a jquery selector for the form

$.rails.enableFormElements @form

Thank you! just saw you responded

The loading animation works except the spinning icon doesn't show up. I'm using Chrome on Windows 7 if that matters. Any help? Thanks!

Thank you so much. This is awesome. Been looking for this for ages.
How do I do this for submit_tag? Couldn't get the spinner working. This is what I have right now
<%= submit_tag :Search, class: "btn btn-primary", data: {disable_with: "Searching..."} %>

You actually can't do this with submit tags because it generates an input field which doesn't allow HTML in the value. You must use a button, but it renders the same and also still submits the form so basically no difference.

Thank you so much Chris for the prompt reply. I don't know how to convert this to f.button

<%= form_tag reply_conversation_path(@conversation), method: :post do %>
<div class="form-group">
<%= text_area_tag 'body', nil, cols: 3, class: 'form-control', placeholder: 'Type your message here', required: true %>
<%= submit_tag "Send Message", class: 'btn btn-primary', data: {disable_with: "Sending..."} %>
<% end %>

Is it possible to convert this to f.button here?

Yep! Just look up the button_tag arguments (can't remember them off the top of my head, but that will show you which arguments you need. It's really simple to migrate it.

Im clicking a link in my navbar...If I wanted to get this same function but have the loading indicator display in the middle of the page instead how would I achieve this?

Could you render a partial or do

disable_with: "<div class="loading-indicator" <="" div="">" then css that class ?

You probably could actually. You'd need to probably do some hacky things for that CSS, but it could work. However, if you're doing something more complicated than just changing the button text, I might encourage you to just use regular old jQuery to listen to the click or form submit and do the work there. Then you can put your loading-indicator div anywhere you like on the page and your CSS can be relative to its parent div.

Awesome, I'll try jquery it to listen for the click on the link, when it does I would then show that div? And that div would then 'disappear' because the new page would have been rendered? Then any css I would just add it to that div class and position it relative to its parent.

I think I got that right? I'm relatively new with using jquery.

Thanks man!

Yeah, so by default your CSS for that div probably needs to be "display: none" so it's hidden. Then when they submit the form, you "display: block" or whichever makes the most sense. As long as you're doing a regular form submit, it'll disappear because of the page load.

If you want the form to be an AJAX form, you can simply hide it after the AJAX request gets a response back.

That should do the trick! Plus this will be a good starter project for using jQuery. :)

Ah Awesome okay. This is actually for when clicking on a link in my navbar. It delays to show the visiting page because of an api call its making to and so it takes a tad before it returns the results and displaying the page.

This is why I initially wanted to add a processing indicator. BUT... to eliminate all this could I have some sort of like background job that runs once a day to get any updated data and store the results somewhere and then when I render that page I just grab those already retrieved results and display those?

Yeah! That would be much better I think. You can write a rake task to do the sync and then use the whenever gem to schedule that to run on a nightly cron.

You the man Oliver! I got my whenever up (think I have syntax correct) and also my rake task set up.

I'm having a brain fart on how to grab that data it retrieved in that task and place it in one of my controllers which eventually will be used in its view.

You'll just need to save those records to the database in the rake task and then load them up in the controller. That should be all you need to do!

Anyone seeing this not work in Safari? It works in Crome.

I see the same issue. Works great in Chrome and Firefox but no Safari love.

Hey Chris, this screencast is an oldie but a goodie. I'm trying to implement this ujs action throughout my new rails app and I'm having success except with the Stripe submit payment button. The button gets disabled through the Stripe javascript call that disables it separately instead of a line of ruby with the button code and I'm unsure as how to incorporate Font Awesome. Have you had any experience integrating this animation on stripe buttons. I have a stackoverflow question addressing it:

I'm wondering if I could just eliminate the $('.submit-button').attr("disabled", "disabled"); line

and instead call the disable_with right from the button code.
What do you think?

Login or Create An Account to join the conversation.

Subscribe to the newsletter

Join 22,346+ developers who get early access to new screencasts, articles, guides, updates, and more.

    By clicking this button, you agree to the GoRails Terms of Service and Privacy Policy.

    More of a social being? We're also on Twitter and YouTube.