2010-08-17 4 views
25

Auparavant, dans les rails 2.3.8 j'ai utilisé les prototypes-helpers link_to_remote et form_remote_for (entre autres).rails3 rails.js et jquery capturant le succès et l'échec des demandes ajax

Ceux-ci avaient l'option :update comme suit:

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

(un exemple de la documentation). Cet exemple, en cas de succès, mettrait à jour l'élément html avec la classe "cart" et, en cas d'échec, la classe "error".

Maintenant, je crois que le modus operandi a changé, au contraire, nous écrivons:

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

et il n'y a pas possibilité de définir :update plus. Au lieu d'un html normal, nous rendons maintenant javascript, comme celui-ci (en jquery):

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

mais comment gérez-vous une situation d'erreur? Est-ce que je le manipule dans mon contrôleur, et utilise des vues séparées?

Il me semblerait utile de pouvoir imiter le comportement que nous avions auparavant. Des idées?

Répondre

71

Ha! Je l'ai trouvé décrit dans l'article this. En rails.js les callbacks suivantes sont vérifiées:

  • ajax: chargement: déclenché avant d'exécuter la requête AJAX
  • ajax: succès: déclenché après une requête AJAX réussie
  • ajax: complet: déclenché après l'AJAX demande est complète, quel que soit l'état de la réponse
  • ajax: échec: déclenché après une requête AJAX a échoué, comme face à ajax: succès

comme le javascript doit être discret, ce couplage n'est pas fait dans le HTML.

Un exemple (du même site): les Rails suivants 2.3.8

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

se traduit à ceci:

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

et à l'intérieur du javascript (application.js), vous liez les événements

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!:)

[MISE À JOUR: 29/12/2011]

Deux événements ont été renommés ces derniers temps:

  • ajax:beforeSend: remplacer la fin ajax:loading
  • ajax:error remplace le ajax:failure (je suppose être plus en ligne avec jQuery lui-même)

Donc mon exemple deviendrait:

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

Pour être complet, les événements et leurs paramètres attendus:

.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) {}) 
+6

Suis-je le seul qui pense a pris du recul en supprimant le simple javascript de Rails? – Amala

+6

Comme css sépare une grande partie de la mise en page du contenu (HTML), il est également préférable de séparer le comportement du HTML (utilisez donc js discret). Bien que cela soit, en effet, plus difficile (au début), il facilite également la lecture de votre HTML/JS (utilisez judicieusement vos noms de classe et vos identifiants), et rend votre JS plus facile à maintenir et à réutiliser dans le long courrier. – nathanvda

+1

'ajax: loading' ne fonctionnait pas pour moi, je devais utiliser 'ajax: before' - juste au cas où quelqu'un d'autre rencontrerait ce problème. (Rails 3.1.1) – tmaximini

4

Les rails connexes 4 guide peut être trouvé à l'adresse: http://guides.rubyonrails.org/working_with_javascript_in_rails.html

Il souligne la documentation des événements à: https://github.com/rails/jquery-ujs/wiki/ajax, comme mentionné par ncherro

les valeurs réelles transmises aux callbacks peuvent être déduites de la méthode ajax jQuery http://api.jquery.com/jquery.ajax/#jQuery-ajax-settings

.bind est dépréciée en faveur de .on par jQuery: http://api.jquery.com/on/

Alors maintenant, l'approche recommandée est:

Modèle:

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

coffeescript:

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