Ruby on rails 将值相关数据属性添加到简单表单复选框集合

Ruby on rails 将值相关数据属性添加到简单表单复选框集合,ruby-on-rails,forms,simple-form,custom-data-attribute,Ruby On Rails,Forms,Simple Form,Custom Data Attribute,我正在为单个集合生成复选框列表,如下所示: = f.input :parts, as:check_boxes, collection: @parts_list 我希望集合中的一些复选框消失/重新出现,具体取决于表单中较高位置的select小部件的值。e、 g.从“机器人选择”中选择“跟踪器机器人”意味着“腿部部分”复选框消失,而“车轮”复选框出现,等等 我想做的是将计算数据属性附加到每个单独的零件复选框,属性值列出可以使用该零件的机器人;然后一些JS将隐藏/显示复选框。但是,我不知道如何使用简

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

= f.input :parts, as:check_boxes, collection: @parts_list
我希望集合中的一些复选框消失/重新出现,具体取决于表单中较高位置的select小部件的值。e、 g.从“机器人选择”中选择“跟踪器机器人”意味着“腿部部分”复选框消失,而“车轮”复选框出现,等等

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

我通常会创建一个自定义的部件输入,但在创建自定义集合输入时似乎存在问题;它在form_builder.rb中查找一个命名的方法集合_parts,它不存在,如果我尝试扩展FormBuilder,它会将我发送到一个大兔子洞中


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

我认为您可以这样做:

= 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

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? }
但输入html似乎不是其中之一

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


这应该可以让您开始了。

让我们假设表单用于订单模型,并且您正在根据名为region的字段的值更改零件集合

更新表单视图。指定表单、区域字段和零件字段的id

在route.rb文件中添加名为parts的新操作

将新操作添加到控制器

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
在application.js中为region字段注册数据更改事件处理程序

这可能更简单

假设

示例代码


如果您克隆并转到/robots

可以看到这一点,但您如何动态地做到这一点?没有可绑定的变量…b.object是集合的单个元素,因此可以执行数据:{identifier:b.object.identifier}等操作,这将为组中的每个复选框提供其自己的数据属性,如果您首先将其放入输入中,则所有复选框的数据属性都与相同的值相反,很抱歉,响应延迟了一年半!我最喜欢这个答案,因为它非常简单,尽管还有额外的Ruby&JS代码需要编写。我还没有测试过它,我已经从那个项目和雇主那里离开很久了,但是——假设它能工作——将每个部分的机器人列表放在一个数据元素中是很有意义的,而且很容易动态匹配。非常感谢。首先,很抱歉延迟了一年半的响应时间!这是一个如此完整的答案,太棒了。非常感谢。最终,我选择了陈硕的答案——尽管它不完整,但它表明我可以用一种非常简单的方式在页面中获得我需要的一切,而不需要使用AJAX。但是对于任何比我的特殊情况更复杂的事情,你的情况看起来是一个很好的选择,我相信我将来会需要它。非常感谢。首先,很抱歉延迟了一年半的响应时间!我喜欢它的代码是多么简单,它很小。我唯一不喜欢的是,它正在客户端构建一块表单,我仍然需要为复选框提供正确的部分名称。但是谢谢你!
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
$('#parts-check-box-list').replaceWith('<%= j(parts_collection(@order, @parts_list)) %>');
$(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'));
  });
});
@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>')
      })          
    })
  })