¿Cuál es una forma elegante de agregar condicionalmente una clase a un elemento HTML en una vista?

103

Ocasionalmente tengo que agregar una clase a un elemento html según una condición. El problema es que no puedo encontrar una forma limpia de hacerlo. Aquí hay un ejemplo de las cosas que he probado:

<div <%= if @status = 'success'; "class='ok'"; end %>>
   some message here
</div>

O

<% if @status == 'success' %>
   <div class='success'>
<% else %>
   <div>
<% end %>
   some message here
</div>

No me gusta el primer enfoque porque se ve abarrotado y es difícil de leer. No me gusta el segundo enfoque porque el anidamiento está arruinado. Sería bueno ponerlo en el modelo, (algo así como @status.css_class), pero eso no pertenece allí. ¿Qué hace la mayoría de la gente?

centeno
fuente

Respuestas:

141

Yo uso la primera forma, pero con una sintaxis un poco más sucinta:

<div class="<%= 'ok' if @status == 'success' %>">

Aunque normalmente debería representar el éxito con trueun ID de registro booleano o numérico y el fracaso con booleano falseo nil. De esta manera, puede probar su variable:

<div class="<%= 'ok' if @success %>">

Una segunda forma que usa el ?:operador ternario es útil si desea elegir entre dos clases:

<div class="<%= @success ? 'good' : 'bad' %>">

Finalmente, puede usar los ayudantes de etiquetas de registro de Rail como div_for, que establecerán automáticamente su ID y clase en función del registro que le proporcione. Dado un Personcon id 47:

# <div id="person_47" class="person good">
<% div_for @person, class: (@success ? 'good' : 'bad') do %>
<% end %>
meagar
fuente
@Anurag, mira esto api.rubyonrails.org/classes/ActionController/… . Cosas bastante bonitas.
maček
gracias por el enlace @macek. esto es muy similar a cómo creo elementos en MooTools :) limpio y ordenado
Anurag
2
Mejor respuesta: evite todo el lío y cambie sus puntos de vista a HAML .
meagar
2
O, mejor aún, a SLIM
Dr.Strangelove
4
@ Dr.Strangelove, ¿podría dar un ejemplo de cómo SLIM o HAML manejarían las clases condicionales de manera más elegante? ¿Qué tal en el caso de múltiples clases condicionales?
Brendon Muir
18

Evitando la lógica en las vistas

El problema con el enfoque estándar es que requiere lógica en forma de if declaraciones o ternarios en la vista. Si tiene varias clases CSS condicionales mezcladas con clases predeterminadas, entonces necesita poner esa lógica en una interpolación de cadenas o etiqueta ERB.

Aquí hay un enfoque actualizado que evita poner lógica en las vistas:

<div class="<%= class_string(ok: @success) %>">
   some message here
</div>

class_string método

El class_stringayudante toma un hash con pares clave / valor que consisten en cadenas de nombres de clases CSS y valores booleanos . El resultado del método es una cadena de clases donde el valor booleano se evalúa como verdadero.

Uso de la muestra

class_names(foo: true, bar: false, baz: some_truthy_variable)
# => "foo baz"

Otros casos de uso

Este ayudante se puede utilizar dentro de ERBetiquetas o con ayudantes de Rails como link_to.

<div class="<%= class_string(ok: @success) %>">
   some message here
</div>

<% div_for @person, class: class_string(ok: @success) do %>
<% end %>

<% link_to "Hello", root_path, class: class_string(ok: @success) do %>
<% end %>

Clases una u otra

Para los casos de uso en los que sería necesario un ternario (por ejemplo @success ? 'good' : 'bad'), pase una matriz donde el primer elemento es la clase para truey el otro es parafalse

<div class="<%= [:good, :bad] => @success %>">

Inspirado por React

Esta técnica está inspirada en un complemento llamado classNames(anteriormente conocido como classSet) de FacebookReact marco front-end .

Uso en sus proyectos de Rails

A partir de ahora, la class_namesfunción no existe en Rails, pero este artículo le muestra cómo agregarla o implementarla en sus proyectos.

Carlos Ramírez III
fuente
2

También puede usar content_for helper, especialmente si el DOM está ubicado en un diseño y desea configurar la clase css dependiendo de la carga parcial.

En el diseño:

%div{class: content_for?(:css_class) ? yield(:css_class) : ''}

En el parcial:

- content_for :css_class do
    my_specific_class

Eso es.

aclamación
fuente