I've been trying to get some dynamic select functionality working, but despite many different tutorial i've yet to get it to work. For ease of reading, i've brought the code examples down to basics. Any advise would be greatly appreciated.
On the faults page, i need to assign a company and contact to the fault, but I only want to be able to see the contacts associated with the selected company
Fault - belongs_to :company, :user, :contact
User - has_many :faults
Contacts - has_and_belongs_to_many :companies
Company - has_and_belongs_to_many :contacts, has_many :faults
/faults/_form.html.erb
<%= f.label :company, "Company:" %>
<%= collection_select(:fault,:company_id,@companies,:id,:full_name, :prompt => "Please select a company") %></br>
<%= f.label :contact, "Contact:" %>
<%= f.collection_select :contact_id, @contacts, :id, :name, :prompt => "Select a Contact" %>
<%= link_to "Add New Contact", {:controller => "companies", :action => "index"}, :confirm => "To add a contact for a company you need to do this from the companies page." %></br>
Gotcha. Using UJS you can dynamically populate your select in 5 steps.
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 %>
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);
})
})
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With