34

我需要为每个控件添加一个自定义 HTMLoption属性select。我在 Rails 中使用 simple_form。有谁知道如何做到这一点?该属性将由客户端 JS 使用。

例如,我想做这样的事情:

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

这将产生(简化):

<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可能看起来像这样:

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

希望避免制作自定义控件/包装器。谢谢!

4

5 回答 5

23

你很近!最简单的方法实际上是在这里不使用 simple_form。这是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 %>

对于您的确切代码,它将是:

<% 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 %>
于 2015-01-16T00:47:33.553 回答
20

仅简单形式:

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

于 2018-02-03T11:41:08.870 回答
1

使用方法的一个(小)缺点是,当简单地将块传递给 tldr 时,任何默认输入 html 选项(如简单表单或类或属性)和任何默认选项(如 )都会f.input do end丢失requiredoptional输入required不会被修饰b.use :input, class: 'input-element'f.input

如果您依赖这些额外的类和属性,则必须手动传递它们(不是干的)。

为了克服这个问题,我为我的特殊选择创建了一个自定义输入,所以我可以像我想要的那样定义我的选择主体(<option>标签),但是选择像往常一样被装饰:

# 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

简单地这样称呼它:

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

options_html是一种解决方法,因为实际上将块传递给我们的自定义输入会更容易:

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

但是由于SimpleForm::FormBuilder#def_input的工作方式,该块在代码甚至触及输入之前就被带走了。所以没有办法不重构 simple_form。

总而言之,这通过在您的视图中为您的特殊选择添加一点额外嘈杂的代码来解决问题。

于 2016-01-16T14:17:08.057 回答
1

对于关联选择:

f.association :product, collection: Product.all.map { |product| [product.name, product.id] }
于 2019-10-12T10:29:22.943 回答
0

这似乎是这样做的正确方法:

Rails 简单表单自定义关联选择字段

于 2013-07-09T18:17:00.147 回答