Cyril Duchon-Doris
Cyril Duchon-Doris

Reputation: 13949

Rails AJAX Feedback, especially on error

I'd like to improve the AJAX feedback in my application (after I POST a remote form in my modals, etc.).

I already have some nice feedback showing a loading animation

$(document).ajaxStart(function(){
    $('.loading-feedback').show()
})

$(document).ajaxStop(function(){
    $('.loading-feedback').hide()
})

But I realize it's not enough : when my AJAX requests trigger a Completed 500 Internal Server Error in 1985ms... well nothing really happens for the user.

I would like, for example, to show an alert message on my frontend.

I already have some code that can display some flash messages I store in AJAX responses, which I'd like to reuse for this (for example, by showing oops, your AJAX request triggered a #{err_code} #{err_description}. Please tell the devs :D

I have the following code which successfully shows bootstrap flashes after AJAX requests (the content/type of the flashes being defined in my controllers)

application_controller.rb

after_filter :ajax_flash
def ajax_flash
  return unless request.xhr?

  if type = priority_flash
    response.headers['X-Message'] = flash[type]  
    response.headers['X-Message-Type'] = type.to_s

    flash.discard  # don't want the flash to appear when you reload page
  end
end

Related javascript

$(document).ajaxComplete(function(e, request, opts) { 
    fireFlash(request.getResponseHeader('X-Message'), request.getResponseHeader('X-Message-Type')); 
    # Where fireFlash is a function that displays a bootstrap alert
});

But now, If there is an error, my controller action will just return. Is it possible to detect this, and for example to fill a flash

flash[:fatal] = "oops, your AJAX request triggered a #{err_code} #{err_description}. Please tell the devs :D"

That would the be displayed on my frontend ? (note that I don't know where to find err_code and err_description)

Upvotes: 0

Views: 158

Answers (2)

max
max

Reputation: 102055

You don't need to use Ajax to create flash messages.

Since flash messages are non-persistent and removed from the session when they are rendered you can just create new flash messages by modifying the document.

This is a minimal flash implementation:

$(document).on('flash', function(e, key, message){
    var $flash = $('<li class="alert flash js-created"></li>')
        .addClass("alert-" + key)
        .html(message);

    $(this).find('.flashes').append($flash);
});

Turbolinks will clean out the flashes for use since it replaces the entire <body>.

You can add a global ajax failure handler by using ajaxError instead of ajaxStop.

var $doc = $(document);
$doc.ajaxError(function(event, jqxhr, settings, thrownError){
   $doc.trigger('flash', ['error', jqxhr.status + thrownError]);
});

Upvotes: 1

vinayakj
vinayakj

Reputation: 5681

Use it this way.

$loader.fadeIn();

jqXHR = $.ajax({
          url: "",
          type: "POST",
          data: {},
          dataType: "json"
        });

jqXHR.done(function( response ) {

});

jqXHR.fail(function( jqXHR, textStatus ) {
      console.log( "Request failed: " + textStatus );
});

jqXHR.always(function( jqXHR, textStatus ) {
      $loader.fadeOut();
});

Upvotes: 0

Related Questions