91 votes

Comment créer plusieurs boutons d'envoi pour le même formulaire dans Rails ?

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 celle 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 puis-je faire cela ? Je ne peux pas modifier l'itinéraire. Existe-t-il un moyen d'envoyer une variable différente qui sera récupérée par [:params] ?

Et si je le fais alors, que dois-je faire dans le contrôleur, mettre en place une déclaration de cas ?

127voto

Anurag Points 66470

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 un résultat :

<input type="submit" value="A" id=".." name="commit" />
<input type="submit" value="B" id=".." name="commit" />

Dans 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, n'oubliez pas que cela couple étroitement votre vue au contrôleur, ce qui n'est peut-être pas très souhaitable.

29voto

masciugo Points 105

Vous pouvez également reconnaître le bouton sur lequel vous avez appuyé en modifiant le nom de son attribut.

<% form_for(something) do |f| %>
    ..
    <%= f.submit 'A', name: 'a_button' %>
    <%= f.submit 'B', name: 'b_button' %>
    ..
<% end %>

C'est un peu gênant car vous devez vérifier la présence des clés de params au lieu de simplement vérifier la valeur de params[:commit] : vous recevrez params[:a_button] ou params[:b_button] selon celui qui a été pressé.

13voto

Tadas Sasnauskas Points 949

Solution similaire à celle proposée par @vss123 sans utiliser de gemmes :

resources :plan do
  post :save, constraints: lambda {|req| req.params.has_key?(:propose)}, action: :propose
  post :save, constraints: lambda {|req| req.params.has_key?(:finalize)}, action: :finalize
end

Remarquez que j'évite d'utiliser la valeur et que j'utilise plutôt le nom de l'entrée, car la valeur du bouton d'envoi est souvent internationalisée ou traduite. Aussi, j'éviterais d'utiliser ceci trop souvent car cela va rapidement encombrer votre fichier routes.

9voto

vss123 Points 193

Nous avons résolu le problème en utilisant contraintes avancées dans les rails.

L'idée est d'avoir le même chemin (et donc le même nom de route et d'action) mais avec des contraintes de routage vers des actions différentes.

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 possède une méthode matches? qui renvoie vrai si le paramètre commit correspond à la valeur attr. d'instance donnée.

Disponible sous forme de bijou commit_param_matching .

3voto

Draknor Points 11

C'est une vieille question, mais comme j'ai été confronté à la même situation, j'ai pensé poster ma solution. J'utilise des constantes de contrôleur pour éviter d'introduire un décalage entre la logique du contrôleur et le bouton de vue.

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 se trouve qu'à un seul endroit - en tant que constante dans le contrôleur. Je n'ai pas encore essayé de comprendre comment le traduire en anglais, cependant.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X