Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CoffeeScript to select form fields dynamically on change and on load

I have a Rails app where I'm trying to select a list of facilities based on what region is selected in a form. So far, I've implemented group_collection_select to do this as well as a bit of CoffeeScript.

It works when creating a new record and selecting a region. The behavior being to only show facilities listed for the selected region. What does not work is when editing a record, selecting the facilities shows all of the facilities grouped by region instead of constraining the facilities to the selected region.

If I select another region and then select the original reason, the proper list of facilities show up.

I'd like to learn how to refactor the CoffeeScript to where when editing the record the function is fired both on page load (when editing) and on change.

Lastly, there are use cases when the transfer_from_id is set to nil/blank and we use a text field called transfer_from_other. Currently if I do not select a facility and fill in transfer_from_other, because of the CoffeeScript loading the facilities in transfer_from_id it will set the transfer_from_id by the first facility in the scope. I'd like to make this to where if no facility is selected, the transfer_from_id is nil so I can use transfer_from_other.

Here's what my code looks like:

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 excerpt

      <%= 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 %>

If my question and examples are not clear, please let me know and I'll be happy to edit.

like image 845
nulltek Avatar asked Sep 01 '14 19:09

nulltek


1 Answers

Regarding updating the select on both page load and on selection change, unless I'm missing something isn't it sufficient to simply break out the select update portion into its own function, that you then call once on page load, and then on each selection change?

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()

Regarding the second part, each time you update the #call_transfer_from_id select, you will lose the blank option. This second version adds in and selects a blank option each time you select a region:

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()
like image 195
Stefan Magnuson Avatar answered Nov 04 '22 06:11

Stefan Magnuson