J'ai besoin de plusieurs boutons d'envoi.
J'ai un formulaire qui crée une instance de Contact_Call.
Un bouton le crée normalement.
L'autre bouton le crée mais doit avoir une valeur d'attribut différente de la valeur par défaut, et il doit également définir l'attribut sur un modèle différent, mais lié, utilisé dans le contrôleur.
Comment je fais ça? Je ne peux pas changer l'itinéraire, donc existe-t-il un moyen d'envoyer une variable différente qui est récupérée par [: params]?
Et si je le fais alors, que dois-je faire dans le contrôleur, configurer une déclaration de cas?
Vous pouvez créer plusieurs boutons d'envoi et fournir une valeur différente à chacun:
<% form_for(something) do |f| %>
..
<%= f.submit 'A' %>
<%= f.submit 'B' %>
..
<% end %>
Cela produira:
<input type="submit" value="A" id=".." name="commit" />
<input type="submit" value="B" id=".." name="commit" />
À l'intérieur de votre contrôleur, la valeur du bouton soumis sera identifiée par le paramètre commit
. Vérifiez la valeur pour effectuer le traitement requis:
def <controller action>
if params[:commit] == 'A'
# A was pressed
elsif params[:commit] == 'B'
# B was pressed
end
end
Cependant, rappelez-vous que cela couple étroitement votre vue au contrôleur, ce qui peut ne pas être très souhaitable.
Il existe également une autre approche, utilisant l'attribut formaction sur le bouton d'envoi:
<% form_for(something) do |f| %>
...
<%= f.submit "Create" %>
<%= f.submit "Special Action", formaction: special_action_path %>
<% end %>
Le code reste propre, car le bouton de création standard n'a besoin d'aucune modification, vous insérez uniquement un chemin de routage pour le bouton spécial:
formaction:
L'URI d'un programme qui traite les informations soumises par l'élément d'entrée, s'il s'agit d'un bouton ou d'une image d'envoi. S'il est spécifié, il remplace l'attribut action du propriétaire du formulaire de l'élément . Source: MDN
Vous pouvez également reconnaître le bouton sur lequel vous avez appuyé en modifiant son nom d'attribut.
<% form_for(something) do |f| %>
..
<%= f.submit 'A', name: 'a_button' %>
<%= f.submit 'B', name: 'b_button' %>
..
<% end %>
C'est un peu inconfortable car vous devez vérifier la présence des clés params au lieu de simplement vérifier params[:commit]
valeur: vous recevrez params[:a_button]
ou params[:b_button]
selon lequel on a appuyé.
Solution similaire à celle suggérée par @ vss123 sans utiliser de gemmes:
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
Notez que j'évite d'utiliser la valeur et que j'utilise le nom d'entrée à la place car la valeur du bouton de soumission est souvent internationalisée/traduite. De plus, j'éviterais de l'utiliser trop car cela encombrerait rapidement votre fichier de routes.
Nous avons résolu en utilisant contraintes avancées dans Rails.
L'idée est d'avoir le même chemin (et donc la même route & action nommée) mais avec des contraintes de routage vers différentes actions.
resources :plan do
post :save, constraints: CommitParamRouting.new("Propose"), action: :propose
post :save, constraints: CommitParamRouting.new("Finalize"), action: :finalize
end
CommitParamRouting
est une classe simple qui a une méthode matches?
qui renvoie vrai si le paramètre de validation correspond à l'instance attr donnée. valeur.
Ceci est disponible sous forme de gemme commit_param_matching .
Une vieille question, mais depuis que je fais face à la même situation, j'ai pensé publier ma solution. J'utilise des constantes de contrôleur pour éviter d'introduire une différence entre la logique du contrôleur et le bouton d'affichage.
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
Et puis dans la vue:
<% form_for(something) do |f| %>
[...]
<%= f.submit SearchController::SEARCH_TYPES[:searchABC] %>
<%= f.submit SearchController::SEARCH_TYPES[:search123] %>
[...]
<% end %>
De cette façon, le texte ne vit qu'en un seul endroit - en tant que constante dans le contrôleur. Cependant, je n'ai pas encore essayé de comprendre comment i18n.
J'ai un nombre variable de boutons d'envoi sur mon formulaire grâce à nested_form_fields, donc juste utiliser le nom ne me suffisait pas. J'ai fini par inclure un champ de saisie masqué dans le formulaire et à utiliser Javascript pour le remplir lorsque l'un des boutons de soumission du formulaire a été enfoncé.