web-dev-qa-db-fra.com

Comment ajouter des paramètres supplémentaires à un formulaire button_to?

Je veux avoir un bouton Submit. Il met à jour un champ sur la soumission; submission.state = :submitted

Maintenant, je pourrais faire un itinéraire personnalisé et une action personnalisée et poster juste à cela. Mais cela semble vraiment lourd. Surtout que je vais aussi avoir un bouton reject et peut-être plus. Avoir besoin d'un itinéraire et d'une action personnalisés pour chacun de ces objectifs me semble carrément ridicule.

Ce serait beaucoup mieux si je pouvais faire quelque chose comme

button_to "Submit", submission_url(submission), :method => :put, :submission => { :state => :submitted }

Qui publierait dans la méthode update de la soumission et ne mettrait à jour que le champ souhaité.

Mais ça ne marche pas. Comment puis-je le faire fonctionner? Ou avez-vous une meilleure idée de la façon de procéder?

31
chadoh

La demande d'extraction } mentionnée par @AugustinRiedinger a été fusionnée et est maintenant disponible à partir de Rails 4.1.0. Ajoutez maintenant l'option params:

params: { state: :submitted }
40
jayelm

Ce n'est pas aussi concis, mais sans l'extension de Rails, cela me permettra de:

= form_for submission, :html => { :class => "button_to" } do |f|
    = f.hidden_field :state, :value => :submitted
    = f.submit "Submit", :class => "link"
11
chadoh

Ajoutez des paramètres: {} à la fin, cela générera hidden_field

<%= button_to user.name, user, class:"btn btn-default", style:"", method: :patch, remote: true, params: { a_field: false, an_other_field:"a new value" } %>
8
Nicolas Maloeuvre

Ainsi, à partir de cette demande d'extraction Rails: https://github.com/Rails/rails/pull/10471

Voici ce que vous pouvez faire pour avoir votre bouton personnalisé.

Dans application_helper.rb, ajoutez ces lignes:

module ApplicationHelper
  // Unfortunately these 2 methods need to be redefined. I don't know how I could access the original ones.
  def token_tag(token=nil)
    if token != false && protect_against_forgery?
      token ||= form_authenticity_token
      tag(:input, type: "hidden", name: request_forgery_protection_token.to_s, value: token)
    else
      ''
    end
  end

  def method_tag(method)
    tag('input', type: 'hidden', name: '_method', value: method.to_s)
  end

  def button_to_with_params(name = nil, options = nil, html_options = nil, &block)
    html_options, options = options, name if block_given?
    options      ||= {}
    html_options ||= {}

    html_options = html_options.stringify_keys
    convert_boolean_attributes!(html_options, %w(disabled))

    url    = options.is_a?(String) ? options : url_for(options)
    remote = html_options.delete('remote')
    params = html_options.delete('params') { Hash.new }

    method     = html_options.delete('method').to_s
    method_tag = %w{patch put delete}.include?(method) ? method_tag(method) : ''.html_safe

    form_method  = method == 'get' ? 'get' : 'post'
    form_options = html_options.delete('form') || {}
    form_options[:class] ||= html_options.delete('form_class') || 'button_to'
    form_options.merge!(method: form_method, action: url)
    form_options.merge!("data-remote" => "true") if remote

    request_token_tag = form_method == 'post' ? token_tag : ''

    html_options = convert_options_to_data_attributes(options, html_options)
    html_options['type'] = 'submit'

    button = if block_given?
      content_tag('button', html_options, &block)
    else
      html_options['value'] = name || url
      tag('input', html_options)
    end

    inner_tags = method_tag.safe_concat(button).safe_concat(request_token_tag)
    params.each do |name, value|
      inner_tags.safe_concat tag(:input, type: "hidden", name: name, value: value.to_param)
    end
    content_tag('form', content_tag('div', inner_tags), form_options)
  end
end

Et pour l'utiliser:

= button_to_with_params 'Awesome button', awesome_action_path, method: :put, :params => {:my_param => 'my_value'}

Prendre plaisir! Amusez-vous bien

3
Augustin Riedinger

Si je lis les choses correctement, ce que vous voulez réellement faire est spécifique lorsqu'un formulaire Rails standard est soumis de manière standard.

Notez que lorsqu'un formulaire est soumis en utilisant, par exemple,.

f.submit "Save Changes"

puis 

params[:commit] = "Save Changes"

L'avantage, c'est que cela peut vous permettre de créer des branches appropriées dans l'action de mise à jour des contrôleurs. 

La mauvaise chose est que c'est fragile. Si un jour vous ou quelqu'un d'autre décide de changer le texte du bouton, les choses se cassent ... ce qui est mauvais.

K

1
KeiferJ

A partir de Rails 3.2.1, vous pouvez ajouter des paramètres supplémentaires au hachage: html_options en utilisant la clé: form.

http://apidock.com/Rails/v3.2.1/ActionView/Helpers/UrlHelper/button_to

Cela n'existait pas avant la version 3.2.1, il fallait donc une solution plus détaillée pour déclarer un formulaire avec des attributs cachés.

0
s01ipsist