It sounds like the answer you're looking for is a custom form builder. You could create your form builder and inherit from the Rails form builder, and then set that form builder as the default across your application. Then you could define an element called dependent_dropdown or cascading_selection, etc. This element would probably take the id of the source dropdown. Your helper would output a collection_select but it would also output some JavaScript that would fire an AJAX call when the source dropdown changes.
Of course, you don't have to do it this way. You could just use a collection_select, add some attributes to the source dropdown (i.e. :class => 'source_for_dependent', :dependent => some_id
), and then hook up some JavaScript in your application.js that looks for collections with the source_for_dependent
class, and when the onchange
event fires it grabs the id from the dependent
attribute and fires an AJAX call.
Either way, here's an example of your JavaScript (using jQuery)
$('select.source_for_dependent').change(function() {
var id = // get the id of the dependent dropdown, perhaps by $(this).attr('dependent')
var dependentDropDown = $('#' + id);
dependentDropDown.empty();
var success = function(response) {
for (var item in response) {
var option = $(document.createElement('option')).val(item.val).html(item.text);
dependentDropDown.append(option);
}
}
$.get('/some_controller/some_action/' + $(this).val(), success);
}
The success handler gets passed into jQuery's get
method. It takes a JSON response as an argument. We loop through the response, and for each item, we create an option
, pulling the value and the text off the item, and we append that to the dependent dropdown. Your controller might look something like this:
def some_action
@obj = SomeClass.find(params[:id])
respond_to do |format|
format.js { render :json => @obj }
end
end
Edit
Which controller you target is up to you. Let's say Dropdown A targets resource A, and Dropdown B targets resource B. An object of type A
should have a list of objects of type B
. If you're going after the show
action for object A
, then your as_json
method for object A
needs to include its B
associations. This article shows examples of this.
Otherwise, you could target the index
action for resource B
. Making B
a nested resource of A
would be an easy way to key off the id of A
to get all objects of type B
which have a foreign key that points to A
.