The Rails form helpers make working with grouped select tags extremely cumbersome because it doesn’t expose the <option>
and <optgroup>
tags in a way that gives developers the control they need over the HTML. Consider the following example:
grouped_options = [
[['United States','US'], 'Canada'],
['Denmark','Germany','France']
]
grouped_options_for_select(grouped_options, nil, divider: '---------')
It emits the following HTML.
<optgroup label="---------">
<option value="US">United States</option>
<option value="Canada">Canada</option>
</optgroup>
<optgroup label="---------">
<option value="Denmark">Denmark</option>
<option value="Germany">Germany</option>
<option value="France">France</option>
</optgroup>
Things get even more convoluted when working with ActiveRecord and groups
class Continent < ActiveRecord::Base
has_many :countries
# attribs: id, name
end
class Country < ActiveRecord::Base
belongs_to :continent
# attribs: id, name, continent_id
end
Rails requires calling a completely different method to generate grouped select tags.
option_groups_from_collection_for_select(@continents, :countries, :name, :id, :name, 3)
It emits the following HTML.
<optgroup label="Africa">
<option value="1">Egypt</option>
<option value="4">Rwanda</option>
...
</optgroup>
<optgroup label="Asia">
<option value="3" selected="selected">China</option>
<option value="12">India</option>
<option value="5">Japan</option>
...
</optgroup>
Want to do that in Superform?
render field(:countries).select do |s|
# Pretend WebSources is an ActiveRecord scope with a "Social" category that has "Facebook, X, etc"
# and a "Search" category with "AltaVista, Yahoo, etc."
Country.select(:id, :name).group_by(:continent) do |continent, countries|
s.optgroup(label: continent.name) do
s.options countries
end
end
end