In the previous post we looked into creating AJAX-based progress indicator. But how do we supposed to tell the user if something goes wrong? Like a problem with backend connection, or database overload.

Here I will show you how to handle errors and display them easily in a fancy manner.

Basics

Simply put, you can’t use built-in Rails tools and redirect the user with flash message to some other page which would handle error messaging. We need to implement all this logic within a single page, without any redirects, because they spoil the AJAX fun.

So we would need:

  • div container, hidden by default, which will be our placeholder for all error messages

  • JQuery to show/hide this container and to change its error message to an actual one

  • Some kind of timer which would help us to gracefully handle request timeouts

Requirements

We take as an example the same Rails application, as in the previous post.

Algorithm

  • User clicks on a checkbox

  • Progress indicator is displayed

  • Some error raises

  • Progress indicator disappears

  • Modal window with error message and close button appears

  • User reads error message and closes the window

Step I - HTML & CSS

I don’t know about you, but I’m definitely not in the mood to reinvent the wheel. To display our fancy error message we would use Twitter Bootstrap along with a useful plugin.

First, we add Twitter Bootstrap gem into our Gemfile:

gem 'bootstrap-sass'

And then install it:

$ bundle install

Now we need to install Modal Window Bootstrap plugin. So we download it and put into vendor/assets/javascripts/ folder.

Then we include it in our code, using app/assets/javascripts/application.js file. Please note that //= symbols here are not the comments:

// This is a manifest file that'll be compiled into application.js, which will include all the files
// listed below.

...

//= require bootstrap-modal
//= require_tree .

We can now move to our app/views/layouts/application.html.erb file and add the appropriate div placeholder there:

<!DOCTYPE html>
<html>
<head>

  ..

</head>
<body>
  <div class="modal fade" id="ajax-error">
    <div class="modal-header">
      <button class="close" data-dismiss="modal">&times;</button>
      <h3>Error</h3>
    </div>
    <div class="modal-body">
      <p></p>
    </div>
  </div>
  <div class="ajax-progress"></div>

  ...

</body>
</html>

Step II - JavaScript

Now we have our div placeholder in place together with the logic of showing, closing and making a window modal.

In order to show this model window, as well as display the actual error message, we need an intermediate JavaScript layer between our Users controller and our presentation layer.

To do this we employ app/views/shared/ajax-progress.js.erb file, which in the previous post was just a simple one-liner:

$(".ajax-progress").hide();

<% if !@ajax_error.nil? %>
  $(".modal-body > p").text("<%= @ajax_error %>")
  $("#ajax-error").modal("show");
<% end %>

Good. The only case left to be taken care of is a request timeout. To handle it properly, we create a timer in app/assets/javascripts/ajax-submit.js file:

// AJAX Form Submit
  $(".submit").on("change",
    function(event) {
      // Show Progress Indicator
      $(".ajax-progress").show();

      // Set Timeout Callback
      window.setTimeout(function() {
        if ($(".ajax-progress").is(":visible")) {
            $(".ajax-progress").hide();
            // Show Error Window
            $(".modal-body > p").text("Request Timeout.");
            $("#ajax-error").modal("show");
        }
      }, 20000);

      ...

    });
// END

As you can see, we use 20-second timer and then display “Request Timeout.” error message.

Step III - Rails

The final piece that left is how to send the actual error message from Users Controller file app/controllers/users_controller.rb:

class UsersController < ApplicationController

  ...

  def update
    @user = User.find(params[:id])
    @user.attributes = params[:user]

    # Handle the error
    if !@user.save(:validate => false)
      @ajax_error = @user.error.full_message
    end

    respond_to do |format|
      format.html { redirect_to users_path }
      format.js { render 'shared/ajax-progress' }
    end
  end

  ...

end

Conclusion

Timeout Error

We’ve created a fancy AJAX-enabled error handling for our example application, using Rails, JQuery, and Twitter Bootstrap with a plugin.