我有一个表单选择语句,如下所示:
= f.select :country_id, @countries.map{ |c| [c.name, c.id] }
这导致此代码:
...
<option value="1">Andorra</option>
<option value="2">Argentina</option>
...
但我想在我的选项中添加自定义HTML属性,如下所示:
...
<option value="1" currency_code="XXX">Andorra</option>
<option value="2" currency_code="YYY">Argentina</option>
...
答案 0 :(得分:342)
Rails可以使用现有的options_for_select帮助程序添加自定义属性以选择选项。你几乎在问题的代码中使用它。使用html5数据属性:
<%= f.select :country_id, options_for_select(
@countries.map{ |c| [c.name, c.id, {'data-currency_code'=>c.currency_code}] }) %>
添加初始选择:
<%= f.select :country_id, options_for_select(
@countries.map{ |c| [c.name, c.id, {'data-currency_code'=>c.currency_code}] },
selected_key = f.object.country_id) %>
如果您需要分组选项,可以使用grouped_options_for_select助手,如下所示(如果@continents是一个大陆对象数组,每个都有一个国家/地区方法):
<%= f.select :country_id, grouped_options_for_select(
@continents.map{ |group| [group.name, group.countries.
map{ |c| [c.name, c.id, {'data-currency_code'=>c.currency_code}] } ] },
selected_key = f.object.country_id) %>
应该转到paul @ pogodan,他发布的不是在文档中发现这个,而是通过阅读rails来源。 https://web.archive.org/web/20130128223827/http://www.pogodan.com/blog/2011/02/24/custom-html-attributes-in-options-for-select
答案 1 :(得分:6)
这不可能直接使用Rails,您必须创建自己的帮助程序来创建自定义属性。也就是说,可能有两种不同的方法来实现您的目标:
(1)在HTML5中使用自定义属性名称。在HTML5中,您可以拥有custom attribute names,但必须预先添加“数据 - ”。这些自定义属性不会随表单一起提交,但可以用来在Javascript中访问您的元素。如果你想完成这个,我建议你创建一个生成这样的选项的帮助器:
<option value="1" data-currecy-code="XXX">Andorra</option>
(2)使用自定义拆分值来提交其他数据。如果您确实要提交货币代码,我建议您创建如下所示的选择框:
= f.select :country_id, @countries.map{ |c| [c.name, "#{c.id}:#{c.currency_code}"] }
这应该生成如下所示的HTML:
<option value="1:XXX">Andorra</option>
<option value="2:YYY">Argentina</option>
然后您可以在控制器中解析:
@id, @currency_code = params[:country_id].split(':')
答案 2 :(得分:6)
您可以按照以下方式执行此操作:
= f.select :country_id, @countries.map{ |c| [c.name, c.id, { 'data-currency-code' => c.currency_code} ] }
答案 3 :(得分:4)
仅在Rails 3中支持额外属性哈希。
options_for_select
我基本上只是复制了Rails 3代码。您需要覆盖这3种方法:
def options_for_select(container, selected = nil)
return container if String === container
container = container.to_a if Hash === container
selected, disabled = extract_selected_and_disabled(selected)
options_for_select = container.inject([]) do |options, element|
html_attributes = option_html_attributes(element)
text, value = option_text_and_value(element)
selected_attribute = ' selected="selected"' if option_value_selected?(value, selected)
disabled_attribute = ' disabled="disabled"' if disabled && option_value_selected?(value, disabled)
options << %(<option value="#{html_escape(value.to_s)}"#{selected_attribute}#{disabled_attribute}#{html_attributes}>#{html_escape(text.to_s)}</option>)
end
options_for_select.join("\n").html_safe
end
def option_text_and_value(option)
# Options are [text, value] pairs or strings used for both.
case
when Array === option
option = option.reject { |e| Hash === e }
[option.first, option.last]
when !option.is_a?(String) && option.respond_to?(:first) && option.respond_to?(:last)
[option.first, option.last]
else
[option, option]
end
end
def option_html_attributes(element)
return "" unless Array === element
html_attributes = []
element.select { |e| Hash === e }.reduce({}, :merge).each do |k, v|
html_attributes << " #{k}=\"#{ERB::Util.html_escape(v.to_s)}\""
end
html_attributes.join
end
有点凌乱,但这是一个选择。我将此代码放在一个名为RailsOverrides
的辅助模块中,然后将其包含在ApplicationHelper
中。如果您愿意,也可以使用插件/ gem。
一个问题是,要利用这些方法,您必须始终直接调用options_for_select
。像
select("post", "person_id", Person.all.collect {|p| [ p.name, p.id, {"data-stuff"=>"html5"} ] })
将产生旧的结果。相反它应该是:
select("post", "person_id", options_for_select(Person.all.collect {|p| [ p.name, p.id, {"data-stuff"=>"html5"} ] }))
同样不是一个很好的解决方案,但要获得非常有用的数据属性可能是值得的。
答案 4 :(得分:0)
我也遇到了这个问题并创建了“enhanced_select”Ruby Gem来解决这个问题。你可以在这里找到它: