You have a form, the form has multiple select drop down boxes, some of them are dependant on choices selected in other boxes, what do you do?
If you have a simple data set, you can go the client side route which is explained very nicely by Ryan Bates in his screencast http://railscasts.com/episodes/88-dynamic-select-menus
If you have a complex data set and you need to refresh from the server side I could not find any good examples. So I spent a good chunk of a Sunday figuring out how to do this. This blog is a demo of how I figured out how to do it using Rails 2.x and RJS. I will try next weekend for the Rails 3 and UJS/Jquery approach.
In my example, im using 3 objects:
Brand - the brand, this is the data in the first select box
SourceCredential - a list of credentials relevant to a brand, this is the field were updating via ajax
BrandSourceCredentialKey - this is the object im trying to create, it relates to a Brand and SourceCredential
Step 1 - Move the select you want to update into a partial, wrap it in a span, and use fields_for around it, instead of form_for. The reason I do this is that the form is not available on the ajax update. (_source_credential_list.html.erb)
<% fields_for(@brand_report_source_credential_key) do |ff| %>
<%= ff.select :source_credential_id , options_from_collection_for_select(@applicable_source_credentials,'id','credential_display_name')%>
<% end %><%= f.label :source_credential_id %><br />
<span id="source_credential_list">
<%= render :partial => 'source_credential_list' %>
</span>
Step 2 - add an onchange listener to the brand select
<%= f.select :brand_id,
options_from_collection_for_select(@all_brands, 'id', 'name', @brand_report_source_credential_key.brand_id),{},
:onChange => remote_function(:url=> {:action=> :credential_list_for_brand},
:with=> "'brand_id=' + this.value" ) %>
Step 3 - add the remote function
def credential_list_for_brand
brand = Brand.find(params[:brand_id])
@applicable_source_credentials = brand.source_credentials
@brand_report_source_credential_key = BrandSourceCredentialKey.new
respond_to do |format|
format.js
end
end
Step 4 - add the rjs (credential_list_for_brand.rjs)
page.replace("source_credential_list", :partial => "source_credential_list", :object => @applicable_source_credentials)
Thats it, this should work for you now!
Comments