2012-03-28 10 views
14

Il problema è che ho un modulo remoto che, in base alla condizione, id mi piace convertire in un modulo non remoto (usando UJS), e quindi inviare. nota che il modulo ha un caricamento di file.Usa JS per cambiare <form> da remoto a non remoto in Rails 3, HAML

Ecco i dettagli: ho inizialmente reso sotto forma remoto utilizzando

= form_for @myobj, :url => {:action=>"remoteAction", :controller=>"myobjects"}, :remote => true do |f| 
... (f.fields....) 

che produce il codice HTML:

<form id="new_myobj" class="new_myobj" method="post" accept-charset="UTF-8" data-remote="true" action="/remoteAction"> 

quando ho fare clic su Invia, come previsto, il modulo viene inviato 'come JS '. nell'azione del controller, eseguo la convalida dei campi all'interno del modulo inviato. Se tutte le convalide passano, eseguo il seguente modello .js.haml:

$('form#new_myobj').removeAttr("data-remote"); 
$('form#new_myobj').attr('enctype', 'multipart/form-data'); 
$('form#new_myobj').attr('action', '/myobjects/regularAction'); 

che cambia con successo il codice HTML della pagina (assistito via Firebug) a:

<form id="new_myobj" class="new_myobj" method="post" accept-charset="UTF-8" enctype="multipart/form-data" action="/myobjects/regularAction"> 

dal momento che il modulo contiene un file.f.file, devo presentare come multipart in modo che l'immagine possa essere caricata, e non posso inviare "AS JS" ora, quando clicco su submit, l'azione controller 'regularAction' è effettivamente chiamata, ma è ancora 'AS JS '

la ricerca ion is, cos'altro ho bisogno di cambiare in HTML così il modulo può essere inviato non-xhr? è legato alle intestazioni?

risposta

4

Il problema è che il tuo approccio per disabilitare l'invio Ajax non è del tutto corretto. Devi eliminare gli eventi JavaScript che sono già stati aggiunti da rails.js (adattatore UJS di Rails) al modulo. È possibile effettuare questa operazione: $('form#new_myobj').unbind() per separare tutti gli eventi associati al modulo. È inoltre necessario $('form#new_myobj').removeAttr('data-remote') e $('form#new_myobj').removeAttr('data-type') per rimuovere gli attributi data-remote e data-type (se esistenti).

+0

Grazie per il tuo suggerimento, così ho aggiunto la chiamata unbind() al mio modello js.haml, ma il secondo invio va comunque all'azione 'regularAction' 'AS JS ' –

+0

$ (' modulo # new_myobj '). Unbind() $ (' modulo # new_myobj '). RemoveAttr ("data-remote"); ... –

+0

c'è qualche altro componente che è necessario separare, forse? –

36

jQuery è un po 'complicato con gli attributi dei dati poiché entrambi legge i tag di dati HTML5 e anche il proprio spazio di archiviazione associato all'elemento DOM, che viene anche chiamato dati. Quando si scrive su un attributo , quel valore viene copiato nella memoria dati di jQuerys (presumibilmente quando viene chiamato il numero data("remote")).

Tuttavia, questo succede solo a se i dati di jQuery sono vuoti per quel nome. Pertanto, l'impostazione l'attributo funzionerà solo una volta, dopodiché verrà utilizzato il valore "cache" anche se l'attributo cambia. Per eliminare davvero il valore , è necessario rimuovere l'attributo e il metodo di memorizzazione di jQuerys proprio nell'ordine. Il motivo è che esiste una funzione di alto livello (element.removeData(…)) e una di livello basso (jQuery. removeData(element, …)). Il primo rilegge l'attributo HTML5 data e lo memorizza nella memoria di jQuery. Ovviamente funziona anche l'insolita funzione di basso livello .

Inoltre, facciamo davvero bisogno di rimuovere l'attributo - impostazione su falsa non è sufficiente in quanto Rails verifica solo se form.data('remote') non è definito (cercarlo in jquery_ujs.js).

TL; DR:

  • attr("data-remote") != data("remote")
  • Queste due linee fare una forma non remota (nuovo). L'ordine conta.
$("form").removeAttr("data-remote"); 
    $("form").removeData("remote"); 

E 'documentato, se si sa in realtà quello che stai cercando:

StackOverflow non consente per pubblicare più di due link, ma puoi indovinare quello removeData. Le funzioni di alto livello sono collegate da quelle di basso livello.

evitare l'errore di autenticità token nel Rails 4+: Come Stan commentato di seguito, solo facendo quanto sopra non riuscirà con un errore InvalidAuthenticityToken. La soluzione alternativa è semplice, vedi qui per i dettagli: https://stackoverflow.com/a/19858504/1684530

+0

Ottimo! Ti darei più di un 'up', se fosse possibile !!! –

+0

Chiaro e preciso, grazie :) – Benj

+2

Ti amo così tanto adesso –