# Best way to client-side load or hide state/province drop down when country is changed?

**URL:** <https://www.ruby-forum.com/t/best-way-to-client-side-load-or-hide-state-province-drop-down-when-country-is-changed/116822>\
**Category:** Rails\
**Created:** [October 10, 2007, 1:54am UTC](https://www.ruby-forum.com/t/best-way-to-client-side-load-or-hide-state-province-drop-down-when-country-is-changed/116822 "2007-10-10T01:54:13Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![Yuval](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/y/977dab/32.png) [@Yuval](https://www.ruby-forum.com/u/Yuval)\
**Post date:** [October 10, 2007, 1:54am UTC](https://www.ruby-forum.com/t/best-way-to-client-side-load-or-hide-state-province-drop-down-when-country-is-changed/116822/1 "2007-10-10T01:54:13Z")

</div>

Maybe I’m just trying too hard, because I have done this plenty of  
times with plain old javascript before Rails entered my life. But now  
that I’m trying to work within the Rails system of form\_for and such,  
I am finding that what should be a simple task has become arduous  
beyond compare. I’m ready to tear out what little hair I have left,  
and I have yet to find anything online that addresses what I thought  
would be a common scenario.

So, the scenario:  
A user create/edit page. When a user selects US or Canada, the drop  
down loads accordingly. If he selects a different country, the  
dropdown disappears. When the form is submitted, the user and his  
address are saved accordingly.

User: has\_one :address  
Address: has\_one :state, has\_one :country

## edit.rhtml:

\<% form\_for :user, :url =\> {:action =\> “update”, :id =\> @user} do |f|  
%\>  
\<%= render :partial =\> “user\_form”, :locals =\> {:f =\> f} %\>  
\<% end %\>

## \_user\_form.rhtml:

First name: \<%= f.text\_field :first\_name %\>  
  
Last name: \<%= f.text\_field :first\_name %\>  
  
\<% fields\_for :address do |a| %\>  
  
City: \<%= a.text\_field :city %\>  
  
Country: \<%= a.select :country\_id, COUNTRIES %\>  
  
State: \<%= a.select :state\_id, STATES %\>  
  
\<% end %\>

At first, I tried putting the state selector and text in its own  
partial, thinking that via a custom onchange event on the country  
selector and by using RJS I would be able to reload the state selector  
from a controller method or hide it altogether. But in practice it  
can’t be done because the state selector needs a form reference and  
the controller can’t pass that in. It got ugly real fast.

So where I stand now, I’m looking at writing a custom javascript  
method, fired from an onchange event on the country selector, that  
would reload the contents of the state selector. Have I missed some  
magical rails ingredient or helper that would make this better? Has it  
just been too long a day? Any help appreciated.

---

<div class="post-metadata">

**Author:** ![Yuval](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/y/977dab/32.png) [@Yuval](https://www.ruby-forum.com/u/Yuval)\
**Post date:** [October 10, 2007, 5:23am UTC](https://www.ruby-forum.com/t/best-way-to-client-side-load-or-hide-state-province-drop-down-when-country-is-changed/116822/2 "2007-10-10T05:23:06Z")

</div>

I got it working by foregoing a form\_for selector for this attribute,  
and using a manually loaded html selector instead. Seems to work as  
desired, though it feels a bit hackish.

---

<div class="post-metadata">

**Author:** ![Yuval](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/y/977dab/32.png) [@Yuval](https://www.ruby-forum.com/u/Yuval)\
**Post date:** [October 10, 2007, 3:48pm UTC](https://www.ruby-forum.com/t/best-way-to-client-side-load-or-hide-state-province-drop-down-when-country-is-changed/116822/3 "2007-10-10T15:48:29Z")

</div>

i dont think that’s ‘hackish’.  
Basically you’re foregoing some automated magic for more control and  
specificity  
which in this case you needed.

---

<div class="post-metadata">

**Author:** ![Yuval](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/y/977dab/32.png) [@Yuval](https://www.ruby-forum.com/u/Yuval)\
**Post date:** [October 10, 2007, 4:16pm UTC](https://www.ruby-forum.com/t/best-way-to-client-side-load-or-hide-state-province-drop-down-when-country-is-changed/116822/4 "2007-10-10T16:16:07Z")

</div>

True true! Just happy to get it working.

---

<div class="post-metadata">

**Author:** ![Yuval](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/y/977dab/32.png) [@Yuval](https://www.ruby-forum.com/u/Yuval)\
**Post date:** [October 10, 2007, 5:09pm UTC](https://www.ruby-forum.com/t/best-way-to-client-side-load-or-hide-state-province-drop-down-when-country-is-changed/116822/5 "2007-10-10T17:09:56Z")

</div>

Yuval wrote:

> True true! Just happy to get it working.

yuval raz?

---

<div class="post-metadata">

**Author:** ![Yuval](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/y/977dab/32.png) [@Yuval](https://www.ruby-forum.com/u/Yuval)\
**Post date:** [October 12, 2007, 9:13pm UTC](https://www.ruby-forum.com/t/best-way-to-client-side-load-or-hide-state-province-drop-down-when-country-is-changed/116822/6 "2007-10-12T21:13:53Z")

</div>

If you want a solution that is more Rails-centric…

First, I created some helper methods just for convenience. (I only  
needed the state\_options one but created the others for testing this  
solution). The xxx\_options simply creates an acceptable collection  
for populating a Rails select. The xxx\_option\_tags return a string of  
option tags with the line breaks removed. That’s necessary for their  
inclusion in a js function below:

in application\_helper.rb:  
…  
def state\_options  
Address::STATES.collect{|state| [state, state]}  
end

def province\_options  
Address::PROVINCES.collect{|state| [state, state]}  
end

def state\_option\_tags  
options\_for\_select(state\_options).gsub("\n", “”)  
end

def province\_option\_tags  
options\_for\_select(province\_options).gsub("\n", “”)  
end  
…

I’ve got an address partial because I will capture addresses for all  
kinds of different things (people, customers, businesses, etc). My  
address partial just consists of a normal ‘fields\_for :address’.  
Here’s the part relevant to the discussion:

```
<%= f.select :state, state_options %>
<%= f.text_field :postal_code %>
<%= f.country_select :country, ['United States',

```

‘Canada’], :selected=\>‘United States’ %\>  
\<%= observe\_field :address\_country,  
:function=\> “switch(value){ case ‘United  
States’: $(‘address\_state’).show();$  
(‘address\_state’).update(’#{state\_option\_tags}’); break; case  
‘Canada’: $(‘address\_state’).show();$  
(‘address\_state’).update(’#{province\_option\_tags}’); break; default: $  
(‘address\_state’).hide();}” %\>

Okay, so what’s going on… I’m making use of the prototype library  
packaged with Rails and the baked-in “observe\_field” helper. This  
helper observes the country select field and fires on a change (the  
country select is rendered with US and Canada at the top before an  
alphabetical listing of countries, and US is selected by default).  
The :function=\>… part is passing a js-function that will become the  
method responsible for handling the change in the observe field. It  
will be wrapped in a function block that looks like: function(object,  
value) {}. That’s where the ‘value’ field comes from. The rest of  
the string is just a switch-statement that loads the appropriate  
values into the select box or hides it all together.

The #{state\_option\_tag} is where the application\_helper.rb comes into  
play. That is evaluated at run time to give the select options you  
need. The net effect is that the js swaps out the tags in  
the address\_select field.
