2010-07-26 8 views
50

Supponiamo di avere un modello di articolo e nella vista "nuova" dell'articolo ho due pulsanti, "Pubblica" e "Salva bozza".Rails: pulsanti di invio multiplo in un modulo

La mia domanda è come sapere quale pulsante si fa clic nel controller.

Ho già una soluzione ma penso che ci sia un modo migliore. Quello che ho attualmente in uso nella vista è:

<div class="actions"> 
    <%= f.submit "Publish" %> 
    <%= f.submit "Save Draft", :name => "commit" %> 
</div> 

Così nel controller, posso usare il params [: commettere] stringa per gestire l'azione.

def create 
    @article = Article.new(params[:article]) 
    if params[:commit] == "Publish" 
    @article.status = 'publish' 
    // detail omitted 
    end 

    @article.save 
end 

Ma penso che l'uso della stringa relativa vista non sia buona. Potresti dirmi un altro modo per realizzare questo?

UPDATE: Poiché questi pulsanti sono nella stessa forma, stanno tutti andando all'azione 'create', e per me va bene. Quello che voglio è gestirlo all'interno dell'azione di creazione, come dare al modello di articolo una colonna di "stato" e contenere "pubblico" o "bozza".

+1

possibile duplicato di [Come posso creare più pulsanti per presentare la stessa forma in Rails?] (Http://stackoverflow.com/questions/3027149/how-do-i-create-multiple-submit- pulsanti-per-stessi-in-forma-in-rotaie) –

risposta

56

Questo è stato coperto in Railscast episode 38. Utilizzando il params hash per individuare quale pulsante è stato cliccato è l'approccio corretto:

Vista:

<%= submit_tag 'Create' %> 
<%= submit_tag 'Create and Add Another', name: 'create_and_add' %> 

Controller:

if params[:create_and_add] 
    # Redirect to new form, for example. 

else 
    # Redirect to show the newly created record, for example. 
end 
+0

Ho guardato l'episodio di Railscasts per una settimana, ma ho sicuramente perso questo. Sembra essere uguale al mio codice, entrambi usano l'hash params, ma ha fatto un lavoro migliore e ho anche migliorato il mio codice. Molte grazie! – kinopyo

+0

Questo diventa piuttosto complicato se si dispone di un partial '_form' che viene utilizzato all'interno delle azioni ** new ** e ** edit **. In tal caso, è necessario configurare la logica del controller sopra in entrambe le azioni ** create ** e ** update **, per tenere conto dei casi in cui l'utente sta creando un nuovo oggetto o modificando uno esistente. – jayp

+0

@jayp questo è quello che sto cercando di fare in questo momento, mi piacerebbe i tuoi pensieri in [la mia domanda] (http://stackoverflow.com/q/42154972/2909897) – mbigras

1

Ricordo di aver incontrato questo problema una volta. Non puoi tenere due pulsanti e quindi chiamare qualche azione basata sui parametri [: commit]. il pulsante di invio onclick chiamerà l'url a cui si riferisce il modulo. Ci sono alcuni cattivi modi per ottenere il comportamento desiderato. Mantieni un pulsante per chiamare l'azione a cui si riferisce il modulo e per ottenere un altro pulsante per chiamare un'azione, ho usato un link_to e poi cambiato gli stili per abbinare un pulsante. Inoltre, in alternativa, puoi usare jQuery per cambiare l'url che il form chiamerebbe, decidendo quindi quale azione viene invocata in fase di esecuzione. Spero che questo ti aiuti.

+0

Scusa se ho dimenticato di dire che stavo cercando di gestirlo nella stessa azione di creazione, ho aggiornato la domanda. Ma ho anche imparato i tuoi consigli su come usare jQuery per cambiare l'url del modulo, è utile. Grazie. – kinopyo

+0

L'unica risposta a [questa domanda] (http://stackoverflow.com/questions/3086609/ruby-on-rails-how-to-have-multiple-submit-buttons-going-to-different-methods-m) funziona per me, e in effetti usa il valore di 'params [: commit]' nel controller per distinguere quale pulsante è stato premuto. Questa è la stringa "X" quando il pulsante di invio è definito nella vista come '<% = submit_tag (" X ")%>'. –

6

abbiamo risolto utilizzando advanced constraints a rotaie.

L'idea è quella di avere lo stesso percorso (e quindi la stessa route denominata azione &) ma con il routing dei vincoli a diverse azioni.

resources :plan do 
    post :save, constraints: CommitParamRouting.new("Propose"), action: :propose 
    post :save, constraints: CommitParamRouting.new("Finalize"), action: :finalize 
end 

CommitParamRouting è una semplice classe che ha un metodo matches? che restituisce vero se il parametro commettere corrisponda alla data attr istanza. valore.

Disponibile come gemma commit_param_matching.

+0

approccio molto interessante, grazie! – kinopyo

+0

questo è geniale. risolve l'inabilità a reindirizzare con il metodo POST. – urmurmur

0

Si potrebbe anche impostare alcuni data attributi sui pulsanti presentare ed utilizzare JavaScript per modificare l'azione form al clic di uno dei pulsanti

+0

che dire di "toccare" sui dispositivi mobili? – sambehera

0

solito i utilizzando il suggerimento dato da John Topley (vedi risposta precedente). un altro modo è usare JQuery/JS cambiando l'Attribute- form action dopo aver fatto clic sul pulsante di invio esempio:

form_tag({} ,:method => 'post', :id => 'reports_action') do 
    ....... 
    ....... 
    submit_tag 'submit', :onclick => "return changeAction();" 
end 

e poi .....

function changeAction(){ 
    $('#reports_action').attr('action','my_new_action'); 
} 
5

può anche essere fatto sul form_for helper simili

<%= f.submit "Publish",name: "publish", class: "tiny button radius success" %> 
<%= f.submit 'Mark as Draft', name: "draft", class: "tiny button radius " %> 

e la logica è la stessa sul controller

if params[:publish] 
     // your code 
    elsif params[:draft] 
     // your code 
    end