it-swarm.com.de

Was ist eine elegante Möglichkeit, einem HTML-Element in einer Ansicht eine Klasse bedingt hinzuzufügen?

Ich muss gelegentlich eine Klasse zu einem HTML-Element hinzufügen, basierend auf einer Bedingung. Das Problem ist, dass ich nicht herausfinden kann, wie ich es sauber mache. Hier ist ein Beispiel für das, was ich ausprobiert habe:

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

ODER

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

Ich mag den ersten Ansatz nicht, weil er überfüllt aussieht und schwer zu lesen ist. Ich mag den zweiten Ansatz nicht, weil die Verschachtelung durcheinander ist. Es wäre schön, es in das Modell aufzunehmen (so etwas wie @status.css_class), aber das gehört nicht dorthin. Was machen die meisten Leute?

93
ryeguy

Ich benutze den ersten Weg, aber mit einer etwas prägnanteren Syntax:

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

In der Regel sollten Sie den Erfolg jedoch mit dem Booleschen Wert true oder einer numerischen Datensatz-ID und den Misserfolg mit dem Booleschen Wert false oder nil darstellen. Auf diese Weise können Sie Ihre Variable einfach testen:

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

Ein zweites Formular mit dem ternären Operator ?: Ist nützlich, wenn Sie zwischen zwei Klassen wählen möchten:

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

Schließlich können Sie Rails Record Tag Helpers wie div_for Verwenden, das Ihre ID und Klasse automatisch basierend auf dem Datensatz festlegt, den Sie ihm geben. Gegeben ein Person mit der ID 47:

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

Vermeiden Sie Logik in den Ansichten

Das Problem beim Standardansatz besteht darin, dass Logik in Form von if -Anweisungen oder Ternären in der Ansicht erforderlich ist. Wenn Sie mehrere bedingte CSS-Klassen mit Standardklassen gemischt haben, müssen Sie diese Logik in eine Zeichenfolgeninterpolation oder ein ERB-Tag einfügen.

Hier ist ein aktualisierter Ansatz, bei dem keine Logik in die Ansichten eingefügt wird:

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

Methode class_string

Der Helfer class_string Nimmt einen Hash mit Schlüssel/Wert-Paaren an, die aus CSS-Klassennamenstrings und Booleschen Werten bestehen. Das Ergebnis der Methode ist eine Zeichenfolge von Klassen, bei der der boolesche Wert als true ausgewertet wird.

Beispielnutzung

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

Andere Anwendungsfälle

Dieser Helfer kann in ERB Tags oder mit Rails Helfern wie link_to Verwendet werden.

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

Entweder/Oder Klassen

Übergeben Sie für Anwendungsfälle, in denen ein Ternär erforderlich wäre (z. B. @success ? 'good' : 'bad'), Ein Array, in dem das erste Element die Klasse für true und das andere für false ist.

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

Inspiriert von React

Diese Technik ist von einem Add-On namens classNames (früher als classSet bekannt) aus dem React -Front-End-Framework von Facebook inspiriert.

Verwenden Sie in Ihren Rails Projekten

Die Funktion class_names Ist derzeit in Rails nicht verfügbar, aber dieser Artikel zeigt Ihnen, wie Sie sie in Ihre Projekte einfügen oder implementieren können.

15

Sie können auch den Helfer content_for verwenden, insbesondere wenn sich das DOM in einem Layout befindet und Sie die CSS-Klasse in Abhängigkeit von dem teilweise geladenen Objekt festlegen möchten.

Auf dem Layout:

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

Zum Teil:

- content_for :css_class do
    my_specific_class

Das ist es.

2
acmoune