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

103

Je dois parfois ajouter une classe à un élément html basé sur une condition. Le problème est que je n'arrive pas à trouver une façon 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 parce que l'emboîtement est foiré. Ce serait bien de le mettre dans le modèle, (quelque chose comme @status.css_class), mais cela n'a pas sa place. Que font la plupart des gens?

Ryeguy
la source

Réponses:

141

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

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

Bien que généralement, vous devriez représenter le succès avec un booléen trueou un ID d'enregistrement numérique, et un échec avec un booléen falseou nil. De cette façon, vous pouvez simplement tester votre variable:

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

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

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

Enfin, vous pouvez utiliser les assistants de balises d'enregistrement de Rail tels que div_for, qui définiront automatiquement votre identifiant et votre classe en fonction de l'enregistrement que vous lui donnez. Étant donné un Personavec l'ID 47:

# <div id="person_47" class="person good">
<% div_for @person, class: (@success ? 'good' : 'bad') do %>
<% end %>
maigre
la source
@Anurag, consultez api.rubyonrails.org/classes/ActionController/… . Des trucs assez sympas.
maček
merci pour le lien @macek. c'est très similaire à la façon dont je crée des éléments sur MooTools :) soigné et bien rangé
Anurag
2
Meilleure réponse: évitez tout le désordre et changez votre point de vue sur HAML .
meagar
2
Ou, encore mieux, à SLIM
Dr.Strangelove
4
@ Dr Strangelove, pourriez-vous donner un exemple de la façon dont SLIM ou HAML géreraient les classes conditionnelles de manière plus élégante? Qu'en est-il dans le cas de plusieurs classes conditionnelles?
Brendon Muir
18

Éviter la logique dans les vues

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

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

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

class_string méthode

L' class_stringassistant prend un hachage avec des paires clé / valeur constituées de chaînes de noms de classe CSS et de 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

Cet assistant peut être utilisé dans des ERBbalises ou avec des assistants Rails tels 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 trueet l'autre pourfalse

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

Inspiré par React

Cette technique est inspirée d'un add-on appelé classNames(anciennement connu sous le nom classSet) du Reactframework frontal de Facebook .

Utilisation dans vos projets Rails

Pour le moment, la class_namesfonction n'existe pas dans Rails, mais cet article vous montre comment l'ajouter ou l'implémenter dans vos projets.

Carlos Ramirez III
la source
2

Vous pouvez également utiliser l'assistant content_for, en particulier si le DOM est situé dans une mise en page et que vous souhaitez définir la classe css en fonction du partiel chargé.

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.

acmoune
la source