rails3 rails.js and jquery catching success and failure of ajax requests

24,763

Solution 1

Ha! I found it described in this article. In rails.js the following callbacks are checked:

  • ajax:loading : triggered before executing the AJAX request
  • ajax:success : triggered after a successful AJAX request
  • ajax:complete : triggered after the AJAX request is complete, regardless the status of the response
  • ajax:failure : triggered after a failed AJAX request, as opposite to ajax:success

As the javascript should be unobtrusive, this coupling is not done in the HTML.

An example (from the same site) : the following Rails 2.3.8

<% form_remote_tag :url => { :action => 'run' },
        :id => "tool-form",
        :update => { :success => "response", :failure => "error" },
        :loading => "$('#loading').toggle()", :complete => "$('#loading').toggle()" %>

is translated to this :

<% form_tag url_for(:action => "run"), :id => "tool-form", :remote => true do %>

and inside some javascript (application.js), you bind the events

jQuery(function($) {
  // create a convenient toggleLoading function
  var toggleLoading = function() { $("#loading").toggle() };

  $("#tool-form")
    .bind("ajax:loading",  toggleLoading)
    .bind("ajax:complete", toggleLoading)
    .bind("ajax:success", function(xhr, data, status) {
      $("#response").html(status);
    });
});

Great! :)

[UPDATE: 29/12/2011]

Two events have been renamed lately:

  • ajax:beforeSend: replace the late ajax:loading
  • ajax:error replaces the ajax:failure (I guess to be more in line with jQuery itself)

So my example would become:

  $("#tool-form")
    .bind("ajax:beforeSend",  toggleLoading)
    .bind("ajax:complete", toggleLoading)
    .bind("ajax:success", function(xhr, data, status) {
      $("#response").html(status);
    });

For completeness, the events and their expected parameters:

 .bind('ajax:beforeSend', function(xhr, settings) {})
 .bind('ajax:success',    function(xhr, data, status) {})
 .bind('ajax:complete', function(xhr, status) {})
 .bind('ajax:error', function(xhr, data, status) {})

Solution 2

The related rails 4 guide can be found at: http://guides.rubyonrails.org/working_with_javascript_in_rails.html

It points to the documentation of the events at: https://github.com/rails/jquery-ujs/wiki/ajax , as mentioned by ncherro

The actual values passed to the callbacks can be inferred from jQuery's ajax method http://api.jquery.com/jquery.ajax/#jQuery-ajax-settings

.bind is deprecated in favor of .on by jQuery: http://api.jquery.com/on/

So now the recommended approach is:

Template:

<%= link_to 'Click me!',
    'path/to/ajax',
    remote: true,
    id: 'button',
    method: :get,
    data: {type: 'text'}
%>

CoffeScript:

$(document).ready ->
  $("#button").on("ajax:success", (e, data, status, xhr) ->
    alert xhr.responseText
  ).on "ajax:error", (e, xhr, status, error) ->
    alert "error"

Solution 3

I know this question is 3 years old, but it comes up high in Google results and some of the events listed above are not used anymore.

See here for a current list - https://github.com/rails/jquery-ujs/wiki/ajax

Share:
24,763

Related videos on Youtube

nathanvda
Author by

nathanvda

Now mainly C++/Ruby-Rails/SQL/Oracle/jQuery/git. I started out programming MC68000 assembler for Sinclair QL when i was 16. Studied Computer Science. Developed mostly in C++ ever after. Occasionally did some c# and java. Moved to Ruby on Rails in 2009.

Updated on July 09, 2022

Comments

  • nathanvda
    nathanvda almost 2 years

    Previously, in rails 2.3.8 i used the prototype-helpers link_to_remote and form_remote_for (amongst others).

    These had the option :update as follows:

    link_to_remote "Add to cart",
      :url => { :action => "add", :id => product.id },
      :update => { :success => "cart", :failure => "error" }
    

    (an example from the documentation). This example would, upon success update the html-element with class "cart", and upon failure the class "error".

    Now i believe the modus operandi has changed, instead we write:

    link_to "Add to cart", :url => {:action => "add", :id => product.id}, 
        :remote => true
    

    and there is no option to set :update anymore. Instead of a normal html, we now render javascript, like this (in jquery) :

    $('.cart').replaceWith(<%= escape_javascript(render :partial => 'cart') %>)
    

    but how do you handle an error situation? Do i handle it in my controller, and use seperate views?

    It would seem useful to me to somehow be able to mimic the behaviour we had before. Any ideas?

  • Amala
    Amala over 13 years
    Am I the only one who thinks they took a step back with removing simple javascript from Rails?
  • nathanvda
    nathanvda over 13 years
    Like css splits much of the layouting from the content (HTML), it is also better to split the behaviour from the HTML (so use unobtrusive js). While this is, indeed, harder (at first), it also makes your HTML/JS easier to read (use your class-names and identifiers wisely), and makes your JS easier to maintain and re-use in the longrun.
  • tmaximini
    tmaximini over 12 years
    'ajax:loading' did not work for me, I had to use 'ajax:before' - just in case anybody else encounters this problem. (Rails 3.1.1)
  • nathanvda
    nathanvda over 12 years
    @Axsuul: please check the code of the rails.js : there is no event variable triggered!
  • benz001
    benz001 about 11 years
    And for the latest jQuery rails callbacks see the GitHub page: github.com/rails/jquery-ujs/wiki/ajax