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.