ruby on rails f. özel niteliklere sahip seçenekleri seçin


116

Bunun gibi bir form seçme ifadem var:

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

Bu kodla sonuçlanan:

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

Ancak seçeneklerime şunun gibi özel bir HTML özelliği eklemek istiyorum:

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

2
Rails bu işlevi sağlamaz, bu işaretlemeyi oluşturmak için bir yardımcı oluşturmanız gerekir. Ayrıca, bahsettiğiniz örneğin geçerli HTML olmadığını unutmayın.
Augusto

Biliyorum, örneğim geçerli html değil ... Sanırım istediğim sonuçları elde etmek için yolumu değiştirmem gerekiyor, teşekkürler!
el_quick

Yanıtlar:


356

Raylar, mevcut options_for_select yardımcısını kullanarak seçenekleri belirlemek için özel nitelikler ekleyebilir. Sorunuzdaki kodda neredeyse doğruydu. Html5 veri özniteliklerini kullanma:

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

Bir ilk seçim eklemek:

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

Gruplanmış seçeneklere ihtiyacınız varsa, grouped_options_for_select yardımcısını şu şekilde kullanabilirsiniz (@continents, her biri bir ülke yöntemine sahip olan bir kıta nesneleri dizisiyse):

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

Bunu belgelerde değil, rayların kaynağını okuyarak bulduğunu bildiren paul @ pogodan'a kredi gitmelidir. https://web.archive.org/web/20130128223827/http://www.pogodan.com/blog/2011/02/24/custom-html-attributes-in-options-for-select


6

Bunu şu şekilde yapabilirsiniz:

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

Doğru, ancak Anatortoise House'un cevabında daha önce bahsedilmişti.
Kelvin

Kabul edilen cevap, Ruby'nin kullanıldığı özel nitelikleri göstermez. Bu nedenle, Ruby ile nasıl yapılacağını gösteren ilk cevap olduğu için daha iyi olduğunu düşünüyorum.
Nikhil Gupte

5

Bu, doğrudan Rails ile mümkün değildir ve özel öznitelikleri oluşturmak için kendi yardımcınızı oluşturmanız gerekir. Bununla birlikte, istediğiniz şeyi başarmanın muhtemelen iki farklı yolu vardır:

(1) HTML5'te özel bir özellik adı kullanma. HTML5'te özel öznitelik adlarına sahip olmanıza izin verilir , ancak bunların başına 'data-' eklenmelidir. Bu özel özellikler, formunuzla birlikte gönderilmez, ancak Javascript'teki öğelerinize erişmek için kullanılabilirler. Bunu başarmak istiyorsanız, aşağıdaki gibi seçenekler üreten bir yardımcı oluşturmanızı tavsiye ederim:

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

(2) Ek veri göndermek için özel bölmeli değerleri kullanma. Para birimi kodunu gerçekten göndermek istiyorsanız, seçim kutunuzu şu şekilde oluşturmanızı tavsiye ederim:

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

Bu, şuna benzeyen HTML oluşturmalıdır:

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

Daha sonra denetleyicinizde ayrıştırabilirsiniz:

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

3
Mükemmel cevap. 1 numaralı yaklaşımı seçtim ve başkalarına yardım etmesi durumunda nasıl yardımcı yaptığımı blogladım. redguava.com.au/2011/03/…
Joel Friedlaender

Diğer yorumcularla aynı fikirde olun - aşağıdaki Anatortoise'ın cevabına bakın!
Jacob

23
>>>>>>>>>>>>> YANLIŞ CEVAP ... KAYDIRMAYA DEVAM ET <<<<<<<<<<<<
stevenspiel

1
Bu, doğrudan Rails'de mümkündür. Bakınız: stackoverflow.com/a/9076805/380607
Magne

Pan, lütfen bu yanıltıcı yanıtı silin.
vemv

4

Ekstra öznitelik karması yalnızca Rails 3'te desteklenir.

Rails 2.x üzerindeyseniz ve geçersiz kılmak istiyorsanızoptions_for_select

Temelde sadece Rails 3 kodunu kopyaladım. Bu 3 yöntemi geçersiz kılmanız gerekir:

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

Biraz dağınık ama bu bir seçenek. Bu kodu, RailsOverridesdaha sonra dahil edeceğim bir yardımcı modüle yerleştiriyorum ApplicationHelper. İsterseniz bir eklenti / mücevher de yapabilirsiniz.

Bir önemli nokta, bu yöntemlerden yararlanmak için her zaman options_for_selectdoğrudan çağırmanız gerektiğidir . Gibi kısayollar

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

eski sonuçları verecektir. Bunun yerine şöyle olmalıdır:

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

Yine harika bir çözüm değil, ancak her zaman bu kadar faydalı veri özniteliğine ulaşmaya değer olabilir.


Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.