option
コントロールの各select
にカスタムHTML属性を追加する必要があります。 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']
]
カスタムコントロール/ラッパーを作成する必要がないことを期待しています。ありがとう!
これはこれを行う正しい方法のようです:
あなたは近いです!最も簡単な方法は、実際にはここで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 %>
シンプルなフォームのみ:
= f.input :group, @groups.map{|l| [l[0], l[1], {data: {type: l[2]}}]}
f.input do end
メソッドを使用した(小さな)欠点は、デフォルトの入力HTMLオプション(単純なフォームのrequired
またはoptional
クラスまたはrequired
属性など)とデフォルトオプション(b.use :input, class: 'input-element'
など)は、単にf.input
にブロックを渡しただけでは失われますtldr:入力が装飾されません。
これらの追加のクラスと属性に依存している場合は、手動で(ドライではなく)渡す必要があります。
これを克服するために、特別な選択のためのカスタム入力を作成しました。これにより、選択の本体を好きなように定義できます(<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をリファクタリングしないと仕方がありません。
これはすべて、特別な選択のためにビューに少し余分なノイズコードを追加することで問題を解決します。
関連付けの場合:
f.association :product, collection: Product.all.map { |product| [product.name, product.id] }