How do I add HTML attributes to select options with Simple Form Rails?

前端 未结 5 1439
天涯浪人
天涯浪人 2020-12-29 20:08

I need to add a custom HTML attribute to each option for a select control. I\'m using simple_form in Rails. Does anyone know how to do this? The at

相关标签:
5条回答
  • 2020-12-29 20:55

    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 %>
    
    0 讨论(0)
  • 2020-12-29 20:57

    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.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
    

    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.

    0 讨论(0)
  • 2020-12-29 21:00

    simple-form only:

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

    0 讨论(0)
  • 2020-12-29 21:10

    This seems to be the correct way of doing this:

    Rails Simple Form custom association select field

    0 讨论(0)
  • 2020-12-29 21:10

    For an association select:

    f.association :product, collection: Product.all.map { |product| [product.name, product.id] }
    
    0 讨论(0)
提交回复
热议问题