CoffeeScript在更改和加载时动态选择表单字段

时间:2014-09-01 19:39:46

标签: jquery ruby-on-rails-3 forms activerecord coffeescript

我有一个Rails应用程序,我正在尝试根据表单中选择的区域选择设施列表。到目前为止,我已经实现了group_collection_select以及一些CoffeeScript。

在创建新记录和选择区域时有效。该行为仅显示为所选区域列出的设施。什么不起作用是在编辑记录时,选择设施会显示按地区分组的所有设施,而不是将设施限制在所选区域。

如果我选择另一个区域然后选择原始原因,则会显示正确的设施列表。

我想学习如何将CoffeeScript重构到编辑记录时,在页面加载(编辑时)和更改时都会触发该函数。

最后,有一些用例,当transfer_from_id设置为nil / blank时,我们使用一个名为transfer_from_other的文本字段。目前,如果我没有选择设施并填写transfer_from_other,由于CoffeeScript加载transfer_from_id中的设施,它将通过范围中的第一个设施设置transfer_from_id。我想把它设置为如果没有选择任何设施,transfer_from_id是零,所以我可以使用transfer_from_other。

以下是我的代码:

calls.js.coffee

jQuery ->
  facilities = $('#call_transfer_from_id').html()

  $('#call_region_id').change ->
    region = $('#call_region_id :selected').text()
    options = $(facilities).filter("optgroup[label=#{region}]").html()

    if options
      $('#call_transfer_from_id').html(options)   
    else
      $('#call_transfer_from_id').empty()

region.rb

has_many :facilities

facility.rb

attr_accessible :region_id
belongs_to :region

_form.html.erb摘录

      <%= f.label :region %>
      <%= f.collection_select(:region_id, Region.all, :id, :area, {:include_blank => true}, {:class => 'select', required: true}) %>
      <%= f.label :Transfer_From %>
      <%= f.grouped_collection_select :transfer_from_id, Region.order(:area), :active_facilities, :area, :id, :facility_name, {include_blank: true}, class: 'select' %>
      <%= f.label :Transfer_From_Other%>
      <%= f.text_field :transfer_from_other %>

如果我的问题和示例不清楚,请告诉我,我将很乐意编辑。

2 个答案:

答案 0 :(得分:6)

关于更新页面加载和选择更改上的选择,除非我遗漏了某些内容并不足以简单地将选择更新部分分解为自己的函数,然后再调用一次页面加载,然后对每个选择进行更改?

jQuery ->
  facilities = $('#call_transfer_from_id').html()

  update_facilities = ->
    region = $('#call_region_id :selected').text()
    options = $(facilities).filter("optgroup[label=#{region}]").html()

    if options
      $('#call_transfer_from_id').html(options)   
    else
      $('#call_transfer_from_id').empty()      

  $('#call_region_id').change ->
    update_facilities()

  update_facilities()

关于第二部分,每次更新#call_transfer_from_id选择时,您将丢失空白选项。每次选择区域时,第二个版本都会添加并选择一个空白选项:

jQuery ->
  facilities = $('#call_transfer_from_id').html()

  update_facilities = ->
    region = $('#call_region_id :selected').text()
    options = $(facilities).filter("optgroup[label=#{region}]").html()

    if options
      # Set the options
      $('#call_transfer_from_id').html(options)
      # Add in a blank option at the top
      $('#call_transfer_from_id').prepend("<option value=''></option>")
      # Ensure that the blank option is selected
      $('#call_transfer_from_id option:first').attr("selected", "selected");
    else
      $('#call_transfer_from_id').empty()      

  $('#call_region_id').change ->
    update_facilities()

  update_facilities()

答案 1 :(得分:0)

所以我一直在讨论这个问题,我想我已经找到了一个分别适用于Chrome和Firefox的解决方案。

jQuery ->
  facilities = $('#call_transfer_from_id').html()

  update_facilities = ->
    region = $('#call_region_id :selected').text()
    options = $(facilities).filter("optgroup[label=#{region}]").html()

    if options
      # Set the options and include a blank option at the top
      $('#call_transfer_from_id').html("<option value=''></option>" + options)
      # Ensure that the blank option is selected
      $('#call_transfer_from_id').attr("selected", "selected")
    else
      $('#call_transfer_from_id').empty()

  $('#call_region_id').change ->
    update_facilities()

  update_facilities()

我能够重构并删除一行代码,并在一行中设置选项和空白选项,而不是使用前置。出于某种原因,Firefox并不喜欢prepend方法。所以通过调用这一行:$('#call_transfer_from_id').html("<option value=''></option>" + options)我能够传递选项并在数组的开头插入一个空白选项。

到目前为止,我已在Chrome和Firefox上进行了测试,并显示以下行为。

创建新呼叫时,设施受区域约束,并在字段中显示空白选项以供选择。如果您输入transfer_from_other地址并保留transfer_from_id为零,则保留nil值。

当编辑已填写transfer_from_other地址的呼叫时,transfer_from_id不再填充列表中的第一个设施,而是列出空白(零)选项。

编辑已分配transfer_from_id的呼叫时,它会保留记录的原始值,但仍然按地区限制。

你能看一下我的代码,看看它是否有意义。我偶然发现这样做,并以某种方式让它发挥作用。试着理解为什么这种方法适用于两种浏览器而不是只适用于Chrome的答案。