How do I add HTML attributes to select options with Simple Form Rails?
You're close! easiest way is actually not using simple_form here. here's the simple_form documentation
<% 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 %>
For your exact code it would be:
<% 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 %>
simple-form only:
= f.input :group, @groups.map{|l| [l[0], l[1], {data: {type: l[2]}}]}
A (small) drawback using f.input do end
method is that any default input html options (like simple form's required
or optional
classes or the required
attribute) and any default options (like b.use :input, class: 'input-element'
) are missing when simply passing a block to f.input
, tldr: the input does not get decorated.
If you rely on these extra classes and attributes, you'd have to manually pass them in (not dry).
To overcome this I've created a custom input for my special selects, so I can define the body of my select like I want (the <option>
tags) but the select gets decorated as usual:
# app/inputs/select_container_input.rbclass 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 endend
Simply call it like this:
<% options_html = capture do %> <option>bla</option><% end %><%= f.input :attribute, as: :select_container, options_html: options_html %>
The options_html
is a workaround, because actually it would be easier to pass in a block to our custom input:
<%= f.input :attribute, as: :select_container do %> <option>bla</option><% end %>
But due to the way SimpleForm::FormBuilder#def_input works, the block gets carried away before code even touches the inputs. So no way without refactoring simple_form.
All in all this solves the problem with a little bit extra noisy code in your views for your special selects.