ruby on rails f。select带自定义属性的选项

我有一个表单select语句,如下所示:

= 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> ... 

Rails可以使用现有的options_for_select帮助程序添加自定义属性来select选项。 你在问题中的代码几乎是正确的。 使用html5数据属性:

 <%= f.select :country_id, options_for_select(@countries.map{ |c| [c.name, c.id, {'data-currency_code'=>c.currency_code}] }) %> 

添加一个初始select:

 <%= 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是一个大陆对象数组,每个都有一个countries方法):

 <%= 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

这不可能直接使用Rails,而且您必须创build自己的帮助器来创build自定义属性。 也就是说,可能有两种不同的方式来实现你想要的:

(1) 在HTML5中使用自定义属性名称。 在HTML5中,您可以拥有自定义属性名称 ,但必须预先填入“data-”。 这些自定义属性将不会与您的表单一起提交,但它们可以用来访问Javascript中的元素。 如果你想完成这个,我会build议创build一个帮助程序来生成这样的选项:

 <option value="1" data-currecy-code="XXX">Andorra</option> 

(2) 使用自定义分割值提交附加数据。 如果你真的想提交货币代码,我build议你创build你的select框如下:

 = 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> 

你可以在你的控制器中parsing:

 @id, @currency_code = params[:country_id].split(':') 

你可以这样做,如下所示:

 = f.select :country_id, @countries.map{ |c| [c.name, c.id, { 'data-currency-code' => c.currency_code} ] } 

额外的属性散列仅在Rails 3中受支持。

如果你在Rails 2.x上 ,并且想要覆盖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"} ] })) 

再次,不是一个很好的解决scheme,但它可能是值得的永远如此有用的数据属性。

我遇到了这个问题,并创build了“enhanced_select”Ruby Gem来解决这个问题。 你可以在这里find它:

https://github.com/bkuhlmann/enhanced_select