Dynamic Select Boxes – Ruby on Rails 3
Over 4 years ago, I wrote a tutorial for doing dynamic (cascading) select boxes.
Still getting comments and emails to this day. Mostly asking how to get this working with rails 3, which has moved from prototype to jquery.
So here's a tutorial for getting 3 select boxes to trigger updates for each other.
First set things up:
I just used the html5 haml twitter bootstrap, etc template. Really useful.
If you need data, here's what I used - put this in your db/seeds.rb file:
Next, setup your model associations:
Genres have many artists.
Artists have many songs.
Genres have many songs through artists.
I'm just using a home controller to setup variables for the index page as well as setup variables for use in the dynamic updating:
Now the view just has the 3 select boxes and the unobtrusive javascript (triggered onchange) to make the ajax calls for updating:
We need our rjs files for updating the select boxes, one for the songs (when artist changes) and one for the artists and songs (when genre changes):
Our routes are simple:
That's it.
UPDATE: Here's an erb alternative for index.html.
And the js.haml can be converted to js.erb by taking #{...} and converting to <%= ... %> :
12 Responses
to “Dynamic Select Boxes – Ruby on Rails 3”
Sorry, comments for this entry are closed at this time.
Thanks for updating this. I love the clear examples that don’t “assume” you know what something does, or why it’s required.
Thank you for this but I am working on ‘erb’ and this example uses ‘haml’. Please how do I make it work on my work environment? Sorry if I sound naive
Foluso – the only file you’ll want to convert to use erb is going to be the index.html.haml.
The others, you can just rename to .js.erb.
For the index.html.erb, just wrap the lines starting with “=” with <% and %>
And instead of :javascript, just wrap with .
I’ve updated the post to have the erb example for that file.
Thank you very much Charlie for your help. I eventually got it to work though I had to adjust the following files too
# app/views/home/update_artists.js.erb
$(‘#artists_select’).html(“”);
$(‘#songs_select’).html(“”);
# app/views/home/update_songs.js.erb
$(‘#songs_select’).html(“”);
Thanks Foluso, updated post with the converted erb – at the bottom.
I know this is beyond the scope of your tutorial, but — let’s say I want to take the results of all three selects, and pass those as parameters to a controller? On the final select, render a partial with the params ?
I figured it out.
When I select the third element, it executes a render partial with a link_to , :controller => ‘controller_name’, :action => ‘action_name’, :parameter1 => params[:select_name1], :parameter2 => params[:select_name2]
Thanks again for a great learning tool.
hahaha back again with another question.
In your example, the elements come back in the order in which they are in the database (song1, then song2, then song3). Of course, in the “real world” the data would be more like “Good Vibrations”, “Surfer Girl”, and “I Get Around”. What if you want the select list to be in alphabetical order? Normally I would pull the data like @songs = Song.find(:all, :order => ‘title ASC’) – how would you do that with the .map?
You can do this many ways.
1) In the models: You can set the default order of all the models. Plus for the has_many associations, you could add an order clause: has_many :songs, :order => :title
2) In the controller: Instead of Genre.all, you would do Genre.order(:name), or instead of artist.songs, you would do artist.songs.order(:title)
Then the map just acts on the ordered collection.
Hi Charlie,
Thanks for this useful tutorial.
How can used it with simple_form?
Bardach5
Hi Charlie,
Thanks for this useful tutorial.
How can use it with simple_form?
Bardach
First of all, thanks for this. It has been an excellent teaching tool for the collection_select dropdown box method for me. That being said, I’m stuck. My dropdown menus aren’t populated with any data! I followed the tutorial exactly the first two times through. THEN I copied and pasted your code to make sure it wasn’t my mistyping that had screwed things up. No luck still. Any suggestions for where my hangup might be?