web-dev-qa-db-fra.com

Rails: boutons de soumission multiple dans un seul formulaire

Disons que j'ai un modèle d'article, et dans la vue "nouvelle" de l'article, j'ai deux boutons, "Publier" et "Enregistrer le brouillon".

Ma question est de savoir comment puis-je savoir quel bouton est cliqué dans le contrôleur.

J'ai déjà une solution mais je pense qu'il doit y avoir une meilleure solution. Ce que j'utilise actuellement dans la vue est:

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

Donc, dans le contrôleur, je peux utiliser la chaîne params [: commit] pour gérer cette action.

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

  @article.save
end

Mais je pense que l'utilisation de la chaîne liée à la vue n'est pas bonne. Pourriez-vous me dire une autre façon d'accomplir cela?

UPDATE : Étant donné que ces boutons sont sous la même forme, ils vont tous à l'action "créer", et c'est OK pour moi. Ce que je veux, c'est gérer cela dans l'action de création, comme donner au modèle d'article une colonne "statut" et contenir "public" ou "brouillon".

59
kinopyo

Cela a été couvert dans Railscast épisode 38 . Utiliser le hachage params pour détecter le bouton sur lequel vous avez cliqué est la bonne approche:

Affichage:

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

Contrôleur:

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

else
  # Redirect to show the newly created record, for example.
end
64
John Topley

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 .

7
siliconsenthil

cela peut aussi être fait sur l'aide form_for comme ceci

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

et la logique est la même sur le contrôleur

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

Je me souviens d'avoir rencontré ce problème une fois. Vous ne pouvez pas conserver deux boutons, puis appeler une action basée sur les paramètres [: commit]. le bouton soumettre onclick va appeler l'url à laquelle le formulaire fait référence. Il existe certaines mauvaises façons d'obtenir le comportement souhaité. Gardez un bouton pour appeler l'action à laquelle le formulaire fait référence et pour obtenir un autre bouton pour appeler une action, j'ai utilisé un link_to puis changé les styles pour correspondre à un bouton. En outre, vous pouvez également utiliser jQuery pour modifier l'URL que le formulaire appelle, ce qui permet de décider quelle action est appelée au moment de l'exécution. J'espère que cela t'aides.

1
Alok Swain

Vous pouvez également définir des attributs data sur les boutons d'envoi et utiliser JavaScript pour modifier l'action form en cliquant sur l'un des boutons

0
dennismonsewicz

j'utilise généralement la suggestion de John Topley (voir la réponse ci-dessus). une autre façon consiste à utiliser JQuery/JS en changeant l'attribut d'action de formulaire - en cliquant sur l'exemple du bouton soumettre:

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

puis .....

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