ruby-on-rails - example - simple_form_for rails 5
¿Cómo agrego atributos HTML para seleccionar opciones con Simple Form Rails? (4)
Necesito agregar un atributo HTML personalizado a cada option
para un control de select
. Estoy usando simple_form en Rails. ¿Alguien sabe como hacer esto? El atributo será consumido por el cliente JS.
Por ejemplo, quiero hacer algo como esto:
<%= f.input :group, collection: @groups, option_html: { data-type: lambda { |g| g[2] } } %>
Lo que produciría (simplificado):
<select>
<option value="1" data-type="primary">First Group</option>
<option value="2" data-type="secondary">Second Group</option>
<option value="3" data-type="secondary">Third Group</option>
</select>
Donde @groups
pueden verse así:
[
[''First Group'', 1, ''primary''],
[''Second Group'', 2, ''secondary''],
[''Third Group'', 3, ''secondary'']
]
Con la esperanza de evitar tener que hacer un control / envoltorio personalizado. ¡Gracias!
¡Usted está cerca! La forma más fácil es en realidad no utilizar simple_form aquí. Aquí está la documentación de simple_form
<% options = @group.map { |g| [g.name, g.id, {''data-type'' => g.group_type}] } %>
<%= f.input :group, label: ''Group'' do %>
<%= f.select :group, options, include_blank: ''Select a Group'', class: ''form-control'' %>
<% end %>
Para su código exacto sería:
<% options = @group.map { |g| [g[0], g[1], {''data-type'' => g[2]}] } %>
<%= f.input :group, label: ''Group'' do %>
<%= f.select :group, options, include_blank: ''Select a Group'', class: ''form-control'' %>
<% end %>
Esta parece ser la forma correcta de hacer esto:
Campo de selección de asociación personalizada de Rails Simple Form
Un (pequeño) inconveniente de usar el método f.input do end
es que todas las opciones html de entrada predeterminadas (como las clases required
u optional
del formulario simple o el atributo required
) y las opciones predeterminadas (como b.use :input, class: ''input-element''
) faltan cuando simplemente se pasa un bloque a f.input
, tldr: la entrada no se decora .
Si confía en estas clases y atributos adicionales, tendría que pasarlos manualmente (no en seco).
Para superar esto, he creado una entrada personalizada para mis selecciones especiales, por lo que puedo definir el cuerpo de mi selección como quiero (las etiquetas <option>
) pero la selección se decora como de costumbre:
# app/inputs/select_container_input.rb
class SelectContainerInput < SimpleForm::Inputs::Base
def input(wrapper_options)
options_html = input_options.delete(:options_html)
# since we pass our options by our self (and have to select the correct
# option), set `selected` to `''''` to prevent rails calling
# `object.send(attribute_name)` only to set `selected` which is not used.
input_options[:selected] = ''''
merged_input_options = merge_wrapper_options(input_html_options, wrapper_options)
@builder.select attribute_name, nil, input_options, merged_input_options do
options_html
end
end
end
Simplemente llámalo así:
<% options_html = capture do %>
<option>bla</option>
<% end %>
<%= f.input :attribute, as: :select_container, options_html: options_html %>
El options_html
es una solución, porque en realidad sería más fácil pasar un bloque a nuestra entrada personalizada:
<%= f.input :attribute, as: :select_container do %>
<option>bla</option>
<% end %>
Pero debido a la forma en que funciona SimpleForm::FormBuilder#def_input , el bloque se deja llevar incluso antes de que el código toque las entradas. Así que de ninguna manera sin refactorizar simple_form.
Todo esto resuelve el problema con un poco más de código ruidoso en sus vistas para sus selecciones especiales.
sólo forma simple:
= f.input :group, @groups.map{|l| [l[0], l[1], {data: {type: l[2]}}]}