2010-08-17 2 views
25

In precedenza, nelle guide 2.3.8 ho utilizzato i prototipi-aiutanti link_to_remote e form_remote_for (tra gli altri).rails3 rails.js e jquery che intercettano il successo e l'insuccesso delle richieste Ajax

Questi avevano la possibilità :update come segue:

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

(un esempio dal documentation). Questo esempio, dopo il successo, aggiorna l'elemento html con la classe "carrello" e, in caso di errore, la classe "errore".

Ora credo che il modus operandi è cambiato, invece scriviamo:

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

e non v'è alcuna opzione per impostare più :update. Invece di un normale html, ora rendiamo javascript, come questo (in jQuery):

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

ma come si fa a gestire una situazione di errore? Lo gestisco nel mio controller e utilizzo le viste separate?

Mi sembrerebbe utile in qualche modo riuscire a simulare il comportamento che avevamo prima. Qualche idea?

risposta

71

Ha! L'ho trovato descritto nell'articolo this. In rails.js seguenti callback vengono controllati:

  • ajax: carico: attivato prima di eseguire la richiesta AJAX
  • Ajax: il successo: attivato dopo una richiesta AJAX successo
  • ajax: completo: innescata dopo l'AJAX richiesta è completa, indipendentemente lo stato della risposta
  • ajax: fallimento: attivato dopo una richiesta AJAX fallito, come opposto a Ajax: il successo

come il JavaScript dovrebbe essere discreto, questo accoppiamento non è fatto nel codice HTML.

Un esempio (dallo stesso sito): le seguenti guide 2.3.8

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

è tradotto a questo:

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

e all'interno di un javascript (application.js), si associa 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); 
    }); 
}); 

Grande!:)

[AGGIORNAMENTO: 29/12/2011]

Due eventi sono stati rinominati ultimamente:

  • ajax:beforeSend: sostituire il ritardo ajax:loading
  • ajax:error sostituisce il ajax:failure (credo di essere più in linea con lo stesso jQuery)

Quindi il mio esempio diventerebbe:

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

Per completezza, gli eventi e le loro parametri previsti:

.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

io sono l'unico che si pensa fatto un passo indietro con la rimozione di JavaScript semplice da Rails? – Amala

+6

Come css divide gran parte del layout dal contenuto (HTML), è anche meglio dividere il comportamento dall'HTML (quindi usa js non invadente). Sebbene questo sia, in effetti, più difficile (all'inizio), rende anche più semplice la lettura del tuo HTML/JS (usa saggiamente i nomi delle classi e gli identificatori) e rende il tuo JS più facile da mantenere e riutilizzare nel longrun. – nathanvda

+1

'ajax: caricamento' non ha funzionato per me, ho dovuto usare 'ajax: prima' - nel caso in cui qualcun altro incontri questo problema. (Rails 3.1.1) – tmaximini

4

I binari correlati 4 guida sono disponibili all'indirizzo: http://guides.rubyonrails.org/working_with_javascript_in_rails.html

Essa ricorda alla documentazione degli eventi a: https://github.com/rails/jquery-ujs/wiki/ajax, come detto da ncherro

i valori effettivi passati ai callback può essere dedotta dal metodo di jQuery ajaxhttp://api.jquery.com/jquery.ajax/#jQuery-ajax-settings

.bind è deprecato in favore di .on da jQuery: http://api.jquery.com/on/

Così ora l'approccio consigliato è:

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"