ruby on rails f.select 具有自定义属性的选项

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5052889/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 00:28:38  来源:igfitidea点击:

ruby on rails f.select options with custom attributes

ruby-on-railsselectattributes

提问by el_quick

I have a form select statement, like this:

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

= f.select :country_id, @countries.map{ |c| [c.name, c.id] }

Which results in this code:

这导致此代码:

...
<option value="1">Andorra</option>
<option value="2">Argentina</option>
...

But I want to add a custom HTML attribute to my options, like this:

但我想在我的选项中添加一个自定义 HTML 属性,如下所示:

...
<option value="1" currency_code="XXX">Andorra</option>
<option value="2" currency_code="YYY">Argentina</option>
...

回答by Anatortoise House

Rails CAN add custom attributes to select options, using the existing options_for_select helper. You almost had it right in the code in your question. Using html5 data-attributes:

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}] }) %>

Adding an initial selection:

添加初始选择:

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

If you need grouped options, you can use the grouped_options_for_select helper, like this (if @continents is an array of continent objects, each having a countries method):

如果您需要分组选项,您可以使用 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) %>

Credit should go to paul @ pogodan who posted about finding this not in the docs, but by reading the rails source. https://web.archive.org/web/20130128223827/http://www.pogodan.com/blog/2011/02/24/custom-html-attributes-in-options-for-select

应该归功于 paul @ pogodan,他发布了有关不是在文档中而是通过阅读 rails 源代码找到的信息。 https://web.archive.org/web/20130128223827/http://www.pogodan.com/blog/2011/02/24/custom-html-attributes-in-options-for-select

回答by Nikhil Gupte

You could do this as follows:

您可以按如下方式执行此操作:

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

回答by Pan Thomakos

This is not possible directly with Rails, and you'll have to create your own helper to create the custom attributes. That said, there are probably two different ways to accomplish what you want:

这在 Rails 中是无法直接实现的,您必须创建自己的助手来创建自定义属性。也就是说,可能有两种不同的方法来完成你想要的:

(1) Using a custom attribute name in HTML5.In HTML5 you are allowed to have custom attribute names, but they have to be pre-pended with 'data-'. These custom attributes will not get submitted with your form, but they can be used to access your elements in Javascript. If you want to accomplish this, I would recommend creating a helper that generates options like this:

(1)在 HTML5 中使用自定义属性名称。在 HTML5 中,您可以使用自定义属性名称,但它们必须以“data-”开头。这些自定义属性不会随您的表单一起提交,但它们可用于在 Javascript 中访问您的元素。如果你想实现这一点,我建议创建一个生成如下选项的助手:

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

(2) Using values with custom splitting to submit additional data.If you actually want to submit the currency-code, I would recommend creating your select box like this:

(2)使用带有自定义拆分的值来提交附加数据。如果您确实想提交货币代码,我建议您像这样创建选择框:

= f.select :country_id, @countries.map{ |c| [c.name, "#{c.id}:#{c.currency_code}"] }

This should generate HTML that looks like this:

这应该生成如下所示的 HTML:

<option value="1:XXX">Andorra</option>
<option value="2:YYY">Argentina</option>

Which you can then parse in your controller:

然后您可以在控制器中解析:

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

回答by mastaBlasta

The extra attributes hash is only supported in Rails 3.

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

If you're on Rails 2.x, and want to override options_for_select

如果您在Rails 2.x 上,并且想要覆盖options_for_select

I basically just copied the Rails 3 code. You need to override these 3 methods:

我基本上只是复制了 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

Kinda messy but it's an option. I place this code in a helper module called RailsOverrideswhich I then include in ApplicationHelper. You can also do a plugin/gem if you prefer.

有点乱,但这是一个选择。我将此代码放在一个名为的帮助程序模块中RailsOverrides,然后将其包含在ApplicationHelper. 如果你愿意,你也可以做一个插件/宝石。

One gotcha is that to take advantage of these methods you must always invoke options_for_selectdirectly. Shortcuts like

一个问题是,要利用这些方法,您必须始终options_for_select直接调用。快捷方式如

select("post", "person_id", Person.all.collect {|p| [ p.name, p.id, {"data-stuff"=>"html5"} ] })

will yield the old results. Instead it should be:

将产生旧的结果。相反,它应该是:

select("post", "person_id", options_for_select(Person.all.collect {|p| [ p.name, p.id, {"data-stuff"=>"html5"} ] }))

Again not a great solution, but it might be worth it to get to the ever so useful data-attribute.

同样不是一个很好的解决方案,但获得如此有用的数据属性可能是值得的。

回答by Brooke Kuhlmann

I ran into this issue as well and created the "enhanced_select" Ruby Gem to solve this problem. You can find it here:

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

https://github.com/bkuhlmann/enhanced_select

https://github.com/bkuhlmann/enhanced_select