7

次のように、単一のコレクションのチェックボックスのリストを生成しています。

= f.input :parts, as:check_boxes, collection: @parts_list

フォームの上位にある選択ウィジェットの値に応じて、コレクション内のいくつかのチェックボックスを非表示/再表示したい。(たとえば、ロボット選択から「トラッカーロボット」を選択すると、「脚」パーツのチェックボックスが消え、「ホイール」チェックボックスが表示されます。など)

私がやりたいのは、計算されたデータ属性を個々のパーツのチェックボックスに添付することです。属性値には、そのパーツを使用できるロボットが一覧表示されます。その後、一部のJSは、チェックボックスを表示/非表示にする作業を行います。ただし、simple_formを使用してこれらのデータ属性を生成する方法がわかりません。

通常はカスタムの「パーツ」入力を作成しますが、カスタムコレクションの入力には問題があるようです。form_builder.rb内の名前付きメソッド(collection_parts)を探しますが、これは存在しません。FormBuilderを拡張しようとすると、大きなうさぎの穴に送られます。

生成されたHTMLにデータ属性をロードするJSを作成することもできますが、Railsデータに基づいてカスタムJSを生成する必要があり、それは間違った方法のように感じます。

4

4 に答える 4

9

フォームがOrderモデル用partsであり、というフィールドの値に基づいてコレクションを変更していると仮定しますregion

フォームビューを更新します。regionフォーム、フィールド、およびフィールドのIDを指定しpartsます。

= simple_form_for(@order, :html => { :id => "order-form"}) do |f|
  = f.input :region, :wrapper_html => { :id => "order-form-region",                      |
      "data-parts-url" => parts_orders_path(:id => @order.id, :region => @order.region)} |

  = f.input :parts, as: check_boxes, collection: @parts_list,                            |
      :wrapper_html => { id' => 'parts-check-box-list'}                                  |

ファイルで呼び出される新しいアクションを追加partsroute.rbます。

resources :orders do
  collection do
    get :parts
  end
end

コントローラに新しいアクションを追加します

class OrdersController < ApplicationController

  # expects id and region as parameters
  def parts
    @order =  params[:id].present? ? Order.find(params[:id]) : Order.new
    @parts_list = Part.where(:region => params[:region])
  end
end

ヘルパーを追加する

def parts_collection(order, parts_list)
  "".tap do |pc| 
    # to generate the markup for collection we need a dummy form
    simple_form_for(order) do |f| 
      pc << f.input(:parts, as: check_boxes, collection: parts_list, 
        :wrapper_html => {:id => 'parts-check-box-list'})
    end
  end
end

アクションのjsビューを追加します(orders/parts.js.erb

$('#parts-check-box-list').replaceWith('<%= j(parts_collection(@order, @parts_list)) %>');

regionのフィールドのデータ変更イベントハンドラーを登録しますapplication.js

$(document).ready(function() {
  $('#order-form').on("change", "#order-form-region", function () {
    // Access the data-parts-url set in the region field to submit JS request
    $.getScript($(this).attr('data-parts-url'));
  });
});
于 2013-02-20T00:18:26.123 に答える
7

私はあなたがこのようにそれを行うことができると思います:

= f.input :parts do
  = f.collection_check_boxes :parts, @parts_list, :id, :to_s, item_wrapper_tag: :label, item_wrapper_class: :checkbox do |b|
    - b.check_box(data: { YOUR DATA ATTRIBUTES HERE }) + b.text
于 2013-02-16T22:16:53.940 に答える
1

これはもっと簡単かもしれません。

仮定

@robots - an array containing the list of robots
@parts - a hash containing a list of parts for each robot

サンプルコード

# controller
@robots = %w[tracker nontracker]
@parts = { tracker: %w[wheels lcd resistor], nontracker: %w[lcd resistor] }

# view
= f.input :robots, as: :select, collection: @robots, input_html: { id: 'robot-select' }

#parts-list

:javascript
  var parts = #{@parts.to_json};

  $(document).ready(function() {
    $('#robot-select').change(function() {
      $('#parts-list').html('');

      $(parts[$(this).val()]).each(function(index, text) {
        $('#parts-list').append('<input type="checkbox" value=' + text + '>' + text + '</input>')
      })          
    })
  })

https://github.com/jvnill/simple_form_search_appのクローンを作成して、次のURLにアクセスすると、これが機能していることがわかります。/robots

于 2013-02-21T16:03:28.917 に答える
0

SimpleFormの一部の入力オプションは、コレクション内のすべてのアイテムに対して呼び出されるラムダを受け入れます。

f.input :role_ids, :collection => (1..10).to_a,
  :label_method => :to_i, :value_method => :to_i,
  :as => :check_boxes, :required=> true,
  :disabled => ->(item){ item.even? }

しかしinput_html、それらの1つではないようです。

解決策は、おそらくデータ属性自体を適用するカスタムSimpleFormコレクション入力を作成することです。おそらくそれほど柔軟ではありませんが、今のところこれが唯一の方法だと思います。

GitHubには、開始するためのチュートリアルページがあります。

于 2013-02-19T23:00:03.820 に答える