Comment ajouter des attributs HTML pour sélectionner des options avec des Rails de formulaire simples?

J'ai besoin d'ajouter un attribut HTML pour chaque option pour un select contrôler. J'utilise simple_form dans Rails. Personne ne sait comment faire cela? L'attribut sera consommé par JS côté client.

, Par exemple, je veux faire quelque chose comme ceci:

<%= f.input :group, collection: @groups, option_html: { data-type: lambda { |g| g[2] } } %>

Qui produirait (simplifié):

<select>
    <option value="1" data-type="primary">First Group</option>
    <option value="2" data-type="secondary">Second Group</option>
    <option value="3" data-type="secondary">Third Group</option>
</select>

@groups pourrait ressembler à ceci:

[
    ['First Group', 1, 'primary'],
    ['Second Group', 2, 'secondary'],
    ['Third Group', 3, 'secondary']
]

En espérant éviter d'avoir à faire un contrôle/wrapper personnalisé. Merci!

21
demandé sur Adrian Mann 2013-07-09 21:40:03

4 réponses

Tu es proche! le moyen le plus simple est de ne pas utiliser simple_form ici. voici la documentation simple_form

<% options = @group.map { |g| [g.name, g.id, {'data-type' => g.group_type}] } %>
<%= f.input :group, label: 'Group' do %>
  <%= f.select :group, options, include_blank: 'Select a Group', class: 'form-control' %>
<% end %>

Pour votre code exact, ce serait:

<% options = @group.map { |g| [g[0], g[1], {'data-type' => g[2]}] } %>
<%= f.input :group, label: 'Group' do %>
  <%= f.select :group, options, include_blank: 'Select a Group', class: 'form-control' %>
<% end %>
16
répondu Blair Anderson 2017-01-12 03:21:36

Simple-seulement sous la forme:

= f.input :group, @groups.map{|l| [l[0], l[1], {data: {type: l[2]}}]}

2
répondu Bruno Porto 2018-02-03 11:41:08

Un (petit) inconvénient en utilisant la méthode f.input do end est que toutes les options html d'entrée par défaut (comme les classes required ou optional ou l'attribut required) et toutes les options par défaut (comme b.use :input, class: 'input-element') sont manquantes lors du simple passage d'un bloc à f.input, tldr: l'entrée n'est pas décorée .

Si vous comptez sur ces classes et attributs supplémentaires, vous devrez les transmettre manuellement (pas sec).

Pour surmonter cela, j'ai créé une entrée personnalisée pour mes sélections spéciales, afin que je puisse définissez le corps de ma sélection comme je veux (les balises <option>) mais la sélection est décorée comme d'habitude:

# app/inputs/select_container_input.rb
class SelectContainerInput < SimpleForm::Inputs::Base 
  def input(wrapper_options)
    options_html = input_options.delete(:options_html)

    # since we pass our options by our self (and have to select the correct
    # option), set `selected` to `''` to prevent rails calling
    # `object.send(attribute_name)` only to set `selected` which is not used.
    input_options[:selected] = ''    

    merged_input_options = merge_wrapper_options(input_html_options, wrapper_options)
    @builder.select attribute_name, nil, input_options, merged_input_options do
      options_html
    end
  end
end

Appelez-le simplement comme ceci:

<% options_html = capture do %>
  <option>bla</option>
<% end %>
<%= f.input :attribute, as: :select_container, options_html: options_html %>

Le options_html est une solution de contournement, car il serait en fait plus facile de passer un bloc à notre entrée personnalisée:

<%= f.input :attribute, as: :select_container do %>
  <option>bla</option>
<% end %>

Mais en raison de la façon dont SimpleForm::FormBuilder#def_input fonctionne, le bloc est emporté avant que le code ne touche même les entrées. Donc pas moyen sans refactoring simple_form.

Tout dans tout cela résout le problème avec un peu de code bruyant supplémentaire dans vos vues pour vos sélections spéciales.

1
répondu Markus 2016-01-16 14:34:25
0
répondu YWCA Hello 2017-05-23 12:02:00