ruby on rails f.seleziona le opzioni con gli attributi personalizzati

Ho una form select statement, come questa:

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

Quale risulta in questo codice:

 ... Andorra Argentina ... 

Ma voglio aggiungere un attributo HTML personalizzato alle mie opzioni, come questo:

 ... Andorra Argentina ... 

Rails PU CAN aggiungere attributi personalizzati per selezionare opzioni, usando l’helper options_for_select esistente. Hai quasi avuto ragione nel codice della tua domanda. Usando gli attributi dei dati html5:

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

Aggiunta di una selezione iniziale:

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

Se hai bisogno di opzioni raggruppate, puoi usare l’helper grouped_options_for_select, come in questo caso (se @continents è una matrice di oggetti continent, ognuno con un metodo Paesi):

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

Il credito dovrebbe andare a paul @ pogodan che ha postato sul fatto di non trovarlo nei documenti, ma leggendo la fonte dei binari. https://web.archive.org/web/20130128223827/http://www.pogodan.com/blog/2011/02/24/custom-html-attributes-in-options-for-select

Questo non è ansible direttamente con Rails, e dovrai creare il tuo helper per creare gli attributi personalizzati. Detto questo, ci sono probabilmente due modi diversi per realizzare quello che vuoi:

(1) Utilizzo di un nome di attributo personalizzato in HTML5. In HTML5 è ansible avere nomi di attributi personalizzati , ma devono essere pre-pended con “data-“. Questi attributi personalizzati non verranno inviati con il modulo, ma possono essere utilizzati per accedere ai tuoi elementi in Javascript. Se vuoi farlo, ti consiglio di creare un helper che generi opzioni come questa:

  

(2) Utilizzo di valori con suddivisione personalizzata per inviare dati aggiuntivi. Se in realtà vuoi inviare il codice valuta, ti consiglio di creare la casella di selezione in questo modo:

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

Questo dovrebbe generare HTML che assomiglia a questo:

   

Che puoi quindi analizzare nel tuo controller:

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

Potresti farlo come segue:

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

L’hash degli attributi extra è supportato solo in Rails 3.

Se utilizzi Rails 2.x , e desideri sovrascrivere options_for_select

Fondamentalmente ho appena copiato il codice di Rails 3. Devi sostituire questi 3 metodi:

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

Un pò disordinato ma è un'opzione. RailsOverrides questo codice in un modulo helper chiamato RailsOverrides che RailsOverrides poi in ApplicationHelper . Puoi anche fare un plugin / gem se preferisci.

Un trucco è che per trarre vantaggio da questi metodi devi sempre invocare options_for_select direttamente. Scorciatoie come

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

produrrà i vecchi risultati. Invece dovrebbe essere:

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

Ancora una volta non un'ottima soluzione, ma potrebbe valerne la pena di ottenere l'attributo dei dati sempre così utile.

Mi sono imbattuto in questo problema e ho creato il Ruby Gem “enhanced_select” per risolvere questo problema. Potete trovare qui:

https://github.com/bkuhlmann/enhanced_select