Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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?

like image 863
nathanvda Avatar asked Aug 17 '10 10:08

nathanvda


3 Answers

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) {})
like image 114
nathanvda Avatar answered Nov 19 '22 21:11

nathanvda


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"

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

like image 1
ncherro Avatar answered Nov 19 '22 21:11

ncherro