2010-07-26 10 views
50

Digamos que tengo un modelo de Artículo, y en la vista del artículo 'nuevo' tengo dos botones, "Publicar" y "Guardar Borrador".Rieles: botones de envío múltiple en un formulario

Mi pregunta es cómo puedo saber en qué botón se hace clic en el controlador.

Ya tengo una solución, pero creo que debe haber una manera mejor. Lo que actualmente se utilizan en la vista es:

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

Así que en el controlador, puedo usar los params [: comprometerse] cadena de manejar esa acción.

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

    @article.save 
end 

Pero creo que utilizar la cadena relacionada con la vista no es buena. ¿Podrías decirme otra forma de lograr esto?

ACTUALIZACIÓN: Dado que estos botones están en la misma forma, todos van a la acción 'crear', y eso está bien para mí. Lo que quiero es manejar eso dentro de la acción de creación, como dar al modelo de artículo una columna de 'estado' y contener 'público' o 'borrador'.

+1

posible duplicado de [¿Cómo se crean múltiples botones para presentar la misma forma en Rails?] (Http://stackoverflow.com/questions/3027149/how-do-i-create-multiple-submit- buttons-for-the-same-form-in-rails) –

Respuesta

56

Esto se cubrió en Railscast episode 38. Usando el hash params para detectar qué botón se hizo clic es el enfoque correcto:

Vista:

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

controlador:

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

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

He estado viendo el episodio de Railscasts durante una semana, pero definitivamente me he perdido esta. Parece ser lo mismo que mi código, ambos usan params hash, pero hizo un mejor trabajo y también mejoré mi código. ¡Muchas gracias! – kinopyo

+0

Esto se vuelve bastante complicado si tiene un parcial '_form' que se usa tanto en las acciones ** new ** como ** edit **. En ese caso, deberá configurar la lógica del controlador anterior en las acciones ** crear ** y ** actualizar **, para tener en cuenta los casos en los que el usuario está creando un nuevo objeto o editando uno existente. – jayp

+0

@jayp esto es lo que estoy tratando de hacer en este momento, me encantaría su opinión en [mi pregunta] (http://stackoverflow.com/q/42154972/2909897) – mbigras

1

Recuerdo haber encontrado este problema una vez. No puede mantener dos botones y luego llamar a alguna acción en función de los params [: commit]. el botón de enviar onclick llamará a la url a la que se refiere el formulario. Hay ciertas malas maneras de obtener el comportamiento deseado. Mantenga un botón para llamar a la acción a la que se refiere el formulario y para obtener otro botón para llamar a una acción, utilicé un link_to y luego cambié los estilos para que coincida con un botón. Además, como alternativa, puede usar jQuery para cambiar la URL a la que llamaría el formulario, por lo tanto, decida qué acción se invoca en el tiempo de ejecución. Espero que esto ayude.

+0

Lo siento, me olvidé de mencionar que estaba tratando de manejar eso en la misma acción de creación, he actualizado la pregunta. Pero también aprendí sus consejos sobre cómo usar jQuery para cambiar la url del formulario, es útil. Gracias. – kinopyo

+0

La única respuesta a [esta pregunta] (http://stackoverflow.com/questions/3086609/ruby-on-rails-how-to-have-multiple-submit-buttons-going-to-different-methods-m) funciona para mí, y de hecho usa el valor de 'params [: commit]' en el controlador para distinguir qué botón se presionó. Esa es la cadena "X" cuando el botón de envío se define en la vista como '<% = submit_tag (" X ")%>'. –

6

Hemos resuelto utilizando advanced constraints en rieles.

La idea es tener la misma ruta (y, por lo tanto, la misma ruta con nombre & acción) pero con restricciones de enrutamiento a diferentes acciones.

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

CommitParamRouting es una clase simple que tiene un método matches? que devuelve verdadero si el PARAM cometer coincide con el attr caso dado. valor.

Esta disponible como una gema commit_param_matching.

+0

enfoque muy interesante, gracias! – kinopyo

+0

esto es brillante. resuelve la imposibilidad de redirigir con el método POST. – urmurmur

0

También podría establecer algunos data atributos en los botones Enviar y utilizar JavaScript para cambiar a cabo la acción form el clic de uno de los botones

+0

¿qué tal en "tocar" en dispositivos móviles? – sambehera

0

generalmente i utilizando la sugerencia dada por John Topley (véase la respuesta anterior). otra forma es utilizar jQuery/JS cambiando el atributo, acción de formulario al hacer clic en el botón de envío ejemplo:

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

y luego .....

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

que también se puede hacer en el form_for helper como este

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

y la lógica es la misma en el controlador

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