Reputation: 4809
I'm using Rails 3. I want to create a select tag with some options grouped and others not grouped. Options would look something like this:
Income
Auto
Fuel
Maintenance
Home
Maintenance
Mortgage
In this example, Income is not a group, but Auto and Home are.
I see three helper methods grouped_options_for_select
and grouped_collection_select
, option_groups_from_collection_for_select
but they all appear to require that you have a group for every option.
Is there a way to use a helper to do this or will I have to generate the HTML myself? I imagine I could use two different helpers to create the options and just append the results of both.
Upvotes: 2
Views: 1298
Reputation: 525
Using Aarons answer as a starting point, I made a version that takes a Hash
as the input.
def grouped_and_ungrouped_options_for_select(grouped_options, selected_key = nil)
body = ''
grouped_options.each do |key, value|
selected = selected_key == value
if value.is_a?(Hash)
body << content_tag(:optgroup, grouped_and_ungrouped_options_for_select(value, selected_key), :label => key)
else
body << content_tag(:option, key, value: value, selected: selected)
end
end
body.html_safe
end
Upvotes: 0
Reputation: 1819
There is no off-the-shelf helper (that I know of) that can do what you need. It's somewhat difficult to do because it's going to depend on your data model. Is it an Array, Hash, parent-child, or many-to-many relationship?
Assuming that it's parent-child, you could use recursion to build it:
def child_options_for_select(collection, children_method, group_label_method, child_value_method, child_label_method, options = {})
body = ''
collection.each do |item|
children = item.send(children_method)
if item.children.count != 0
body << content_tag(:optgroup, child_options_for_select(children, children_method, group_label_method, child_value_method, child_label_method, options), :label => item.send(group_label_method))
else
body << content_tag(:option, item.send(child_label_method), :value => item.send(child_value_method))
end
end
body.html_safe
end
Example usage in your view:
<%= select_tag 'foo', child_options_for_select(@categories.roots, :children, :to_s, :id, :to_s) %>
Note that this is fairly slow as it involves several round trips to the database.
Upvotes: 3