Icon_search
Charlie

Dynamic Select Menus in Rails using Observe_Field

Posted on 03/16/2010 by Charlie
 | 

I frequently find myself building forms which contain dynamic select menus. This means that a user selects a choice from one menu, and that choice populates options into a second menu. An example of this might be a scenario where the user selects their state from a drop-down menu, then selects their city from a second menu. We only want that second menu to contain cities appropriate for the user's state, but when the user first loads the page we don't know what state to pull cities for, so we have to wait for that input to populate the second field.

I had been using Javascript to help solve this problem, as described in this Railscast, and that worked just fine until I had to change the JS framework on a certain site from Prototype to jQuery as part of a sitewide upgrade. That caused syntax problems with the JS that was driving my dynamic menus.

Now, I could have gone through the Javascript and just changed all my Prototype syntax to jQuery, but I started wondering if there was a better way to accomplish the same trick without using Javascript (and therefore making the whole deal JS framework-agnostic).

It turns out that making use of the observe_field helper in Rails makes this process pretty simple, and requires no explicit JS code.

I'll outline the process here...

First, let's look at the basic elements of the form in my view:

The first field in the form is a select menu which gathers all the states in the database and offers them as choices. The next bit of code is our observe_field helper, which observes the state selector and fires the "update_city_menu" action when it is changed. The last bit is an empty div where we are going to put our second select menu once we have values for it.

The next thing we'll to do is set up the "update_city_menu" action in the controller.

All it does is find which state in the database the user has selected, and assigns an instance variable to it.

Finally, we set up a view for the output (in this case, called update_city_menu.html.erb)

In this case I coded it so that the second drop-down menu only appears if it gets populated with actual choices. If you want the second menu to always be visible and to display a message if there are no options, you could write your view like this:

I'm a lot happier with this solution than I was with the JS solution because it takes a lot less code and and works the same whether you're using Prototype or jQuery.

Tagged:  dynamic select menus, ruby on rails, ruby, rails, observe field, javascript, jquery, prototype