web-dev-qa-db-fra.com

Quelle est une manière élégante d'ajouter conditionnellement une classe à un élément HTML dans une vue?

Je dois parfois ajouter une classe à un élément html en fonction d'une condition. Le problème est que je ne peux pas trouver une manière propre de le faire. Voici un exemple de ce que j'ai essayé:

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

OU

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

Je n'aime pas la première approche car elle est encombrée et difficile à lire. Je n'aime pas la deuxième approche car l'emboîtement est foiré. Ce serait bien de le mettre dans le modèle, (quelque chose comme @status.css_class), mais cela n'y appartient pas. Que font la plupart des gens?

93
ryeguy

J'utilise la première façon, mais avec une syntaxe un peu plus succincte:

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

Bien qu'en général, vous devriez représenter le succès avec booléen true ou un ID d'enregistrement numérique, et l'échec avec booléen false ou nil. De cette façon, vous pouvez simplement tester votre variable:

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

Un deuxième formulaire utilisant le ternaire ?: L'opérateur est utile si vous souhaitez choisir entre deux classes:

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

Enfin, vous pouvez utiliser Rail's record tag helpers comme div_for, qui définira automatiquement votre ID et votre classe en fonction de l'enregistrement que vous lui fournissez. Étant donné un Person avec l'ID 47:

# <div id="person_47" class="person good">
<% div_for @person, class: (@success ? 'good' : 'bad') do %>
<% end %>
128
meagar

Éviter la logique dans les vues

Le problème avec l'approche standard est qu'elle nécessite une logique sous la forme d'instructions if ou de ternaires dans la vue. Si vous avez plusieurs classes CSS conditionnelles mélangées avec des classes par défaut, vous devez mettre cette logique dans une interpolation de chaîne ou une balise ERB.

Voici une approche mise à jour qui évite de mettre toute logique dans les vues:

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

class_string méthode

Le class_string helper prend un hachage avec des paires clé/valeur composées de chaînes de nom de classe CSS et valeurs booléennes . Le résultat de la méthode est une chaîne de classes où la valeur booléenne est évaluée à true.

Exemple d'utilisation

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

Autres cas d'utilisation

Cette aide peut être utilisée dans les balises ERB ou avec les aides Rails telles que 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 %>

Soit/Ou Classes

Pour les cas d'utilisation où un ternaire serait nécessaire (par exemple @success ? 'good' : 'bad'), passez un tableau où le premier élément est la classe pour true et l'autre est pour false

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

Inspiré par React

Cette technique est inspirée d'un module complémentaire appelé classNames (anciennement classSet) du framework front-end React de Facebook.

Utilisation dans vos projets Rails

À partir de maintenant, le class_names la fonction n'existe pas dans Rails, mais cet article vous montre comment l'ajouter ou l'implémenter dans vos projets.

15
Carlos Ramirez III

Vous pouvez également utiliser l'assistant content_for, en particulier si le DOM est situé dans une présentation et que vous souhaitez définir la classe css en fonction de la charge partielle.

Sur la mise en page:

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

Sur le partiel:

- content_for :css_class do
    my_specific_class

C'est ça.

2
acmoune