¿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?

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

@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.


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.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.