ruby on rails - tag - ¿Cómo creo varios botones de envío para el mismo formulario en Rails?
nested form rails (7)
Lo resolvimos usando restricciones avanzadas en los rieles.
La idea es tener la misma ruta (y, por lo tanto, la misma ruta y acción nombradas), pero con restricciones de enrutamiento para 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 que matches?
que devuelve verdadero si el param de confirmación coincide con la instancia dada attr. valor.
Esta disponible como una gema commit_param_matching .
Necesito tener múltiples botones de envío.
Tengo un formulario que crea una instancia de Contact_Call.
Un botón lo crea como normal.
El otro botón lo crea pero necesita tener un valor de atributo diferente del predeterminado, y también necesita establecer el atributo en un modelo diferente, pero relacionado, utilizado en el controlador.
¿Cómo puedo hacer eso? No puedo cambiar la ruta, ¿hay alguna manera de enviar una variable diferente que sea captada por [: params]?
Y si lo hago entonces, ¿qué debo hacer en el controlador, configurar una declaración de caso?
Puede crear múltiples botones de envío y proporcionar un valor diferente para cada uno:
<% form_for(something) do |f| %>
..
<%= f.submit ''A'' %>
<%= f.submit ''B'' %>
..
<% end %>
Esto dará como resultado:
<input type="submit" value="A" id=".." name="commit" />
<input type="submit" value="B" id=".." name="commit" />
Dentro de su controlador, el valor del botón enviado se identificará mediante el parámetro commit
. Verifique el valor para hacer el procesamiento requerido:
def <controller action>
if params[:commit] == ''A''
# A was pressed
elsif params[:commit] == ''B''
# B was pressed
end
end
Sin embargo, recuerde que esto ajusta estrechamente su punto de vista con el controlador, que puede no ser muy conveniente.
Solución similar a la sugerida por @ vss123 sin usar gemas:
resources :plan do
post :save, constraints: lambda {|req| req.params.key?(:propose)}, action: :propose
post :save, constraints: lambda {|req| req.params.key?(:finalize)}, action: :finalize
end
Tenga en cuenta que evito el uso de valor y uso el nombre de entrada en su lugar dado que el valor del botón de envío a menudo se internacionaliza / traduce. Además, evitaría usar esto demasiado ya que desordenará rápidamente su archivo de rutas.
También hay otro enfoque, usando el atributo de formación en el botón de envío:
<% form_for(something) do |f| %>
...
<%= f.submit "Create" %>
<%= f.submit "Special Action", formaction: special_action_path %>
<% end %>
El código permanece limpio, ya que el botón de creación estándar no necesita ningún cambio, solo inserta una ruta de enrutamiento para el botón especial:
formacion:
El URI de un programa que procesa la información presentada por el elemento de entrada, si es un botón o imagen de envío. Si se especifica, anula el atributo de acción del propietario del formulario del elemento . Fuente: MDN
También puede reconocer qué botón se presionó cambiando su nombre de atributo.
<% form_for(something) do |f| %>
..
<%= f.submit ''A'', name: ''a_button'' %>
<%= f.submit ''B'', name: ''b_button'' %>
..
<% end %>
Es un poco incómodo porque tienes que verificar la presencia de claves params en lugar de simplemente verificar el valor de params[:commit]
: recibirás params[:a_button]
o params[:b_button]
dependiendo de cuál se haya presionado.
Tengo una cantidad variable de botones de envío en mi formulario gracias a nested_form_fields, por lo que usar el nombre no fue suficiente para mí. Terminé incluyendo un campo de entrada oculto en el formulario y usando Javascript para completarlo cuando se presionó uno de los botones de envío de formulario.
Una vieja pregunta, pero como he estado lidiando con la misma situación, pensé en publicar mi solución. Estoy usando constantes de controlador para evitar introducir una discrepancia entre la lógica del controlador y el botón de vista.
class SearchController < ApplicationController
SEARCH_TYPES = {
:searchABC => "Search ABCs",
:search123 => "Search 123s"
}
def search
[...]
if params[:commit] == SEARCH_TYPES[:searchABC]
[...]
elsif params[:commit] == SEARCH_TYPES[:search123]
[...]
else
flash[:error] = "Search type not found!"]
[...]
end
end
[...]
end
Y luego en la vista:
<% form_for(something) do |f| %>
[...]
<%= f.submit SearchController::SEARCH_TYPES[:searchABC] %>
<%= f.submit SearchController::SEARCH_TYPES[:search123] %>
[...]
<% end %>
De esta forma, el texto solo vive en un lugar, como una constante en el controlador. Sin embargo, todavía no he intentado descubrir cómo hacerlo.