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.
- Add class names to your selects in the view
- Add JavaScript (or CoffeeScript) to watch the changes on the select element
- Create a controller method to fetch the info you need based on your selection
- Add a route to match your new controller method
- Create a UJS view to update your contacts select
So,
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"} %>
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()
Update your faults controller
def get_contacts @company = Company.find params[:company_id] @contacts = @company.contacts end
Add a route to your new method
resources :faults do collection do get 'get_contacts', to: "faults#get_contacts" end end
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 %>