web-dev-qa-db-ja.com

Simple Form RailsでHTML属性を追加してオプションを選択するにはどうすればよいですか?

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']
]

カスタムコントロール/ラッパーを作成する必要がないことを期待しています。ありがとう!

27
YWCA Hello

これはこれを行う正しい方法のようです:

Railsシンプルフォームカスタム関連付け選択フィールド

0
YWCA Hello

あなたは近いです!最も簡単な方法は、実際にはここで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 %>
18
Blair Anderson

シンプルなフォームのみ:

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

10
Bruno Porto

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をリファクタリングしないと仕方がありません。

これはすべて、特別な選択のためにビューに少し余分なノイズコードを追加することで問題を解決します。

1
Markus

関連付けの場合:

f.association :product, collection: Product.all.map { |product| [product.name, product.id] }
0
Joshua Muheim