7

我正在为单个集合生成一个复选框列表,如下所示:

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

我希望集合中的一些复选框消失/重新出现,具体取决于表单中较高的选择小部件的值。(例如从Robot select中选择“Tracker Robot”意味着“Legs”部分复选框消失,“Wheels”复选框出现等)

我想做的是将计算数据属性附加到每个单独的零件复选框,属性值列出可以使用该零件的机器人;然后一些 JS 将完成隐藏/显示复选框的工作。但是,我不知道如何使用 simple_form 生成这些数据属性。

我通常会创建一个自定义“部件”输入,但制作自定义集合输入似乎有问题;它在 form_builder.rb 中寻找一个命名方法 (collection_parts),但它不存在,如果我尝试扩展 FormBuilder,它会让我陷入一个大兔子洞。

我可以编写一些 JS 来将数据属性加载到生成的 HTML 中,但是我必须根据我的 Rails 数据生成自定义 JS,这感觉是错误的做法。

4

4 回答 4

9

假设表单用于Order模型,并且您正在parts根据名为 的字段的值更改集合region

更新表单视图。指定表单、region字段和parts字段的 ID。

= 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'}                                  |

parts添加在route.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并转到/robots

于 2013-02-21T16:03:28.917 回答
0

SimpleForm 中的一些输入选项接受为集合中的每个项目调用的 lambda:

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似乎不是其中之一。

解决方案可能是创建一个应用数据属性本身的自定义 SimpleForm 集合输入。也许没有那么灵活,但我认为这是目前唯一的方法。

GitHub 上有一个教程页面可以帮助您入门。

于 2013-02-19T23:00:03.820 回答