Rails - Dynamic Select - Collection Select

Vanilla JS Option

This can be achieved with vanilla javascript only. Make sure that there is a route at companies/[id]/contacts.json which returns correct data.

const select = document.querySelector('#company_id');
select.addEventListener('change',function(e) {
  axios.get(`/companies/${e.target.value}/contacts.json`)
    .then((res) => {
      let contactSelect = document.querySelector('#contact_id')
      contactSelect.innerHTML = ''
      res.data.map((model, i) => {
        contactSelect.options[i] = new Option(model.name, model.id);
      })
    })
});

Gotcha. Using UJS you can dynamically populate your select in 5 steps.

  1. Add class names to your selects in the view
  2. Add JavaScript (or CoffeeScript) to watch the changes on the select element
  3. Create a controller method to fetch the info you need based on your selection
  4. Add a route to match your new controller method
  5. Create a UJS view to update your contacts select

So,

  1. Add class names:

    <%= f.label :company, "Company:" %>
    <%= collection_select(:fault,:company_id,@companies,:id,:name, {:prompt => "Please select a company"}, {:class => "company_selection"}) %>
    <%= f.label :contact, "Contact:" %>
    <%= f.collection_select :contact_id, @contacts, :id, :name, {:prompt => "Select a Contact"}, {:class=>"contact_selection"} %>
    
  2. Throw in some CoffeeScript (app/assets/javascripts/faults.js.coffee)

    $(document).ready ->
      $(".company_selection").on "change", ->
        $.ajax
          url: "/faults/get_contacts"
          type: "GET"
          dataType: "script"
          data:
            company_id: $('.company_selection option:selected').val()
    
  3. Update your faults controller

    def get_contacts
      @company = Company.find params[:company_id]
      @contacts = @company.contacts
    end
    
  4. Add a route to your new method

    resources :faults do
      collection do
        get 'get_contacts', to: "faults#get_contacts"
      end 
    end
    
  5. Add the UJS file (app/views/faults/get_contacts.js.erb)

    $('.contact_selection').empty();
    $('.contact_selection').append( $('<option>Select the Contact</option>'));
    <% @contacts.each do |contact| %>
      $('.contact_selection').append($('<option value="<%= contact.id %>"><%= contact.name %></option>'));
    <% end %>