Какой элегантный способ условно добавить класс к элементу HTML в представлении?

104

Иногда мне приходится добавлять класс к элементу html в зависимости от условия. Проблема в том, что я не могу придумать чистый способ сделать это. Вот пример того, что я пробовал:

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

ИЛИ

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

Мне не нравится первый подход, потому что он многолюдный и трудный для чтения. Второй подход мне не нравится, потому что вложение лажается. Было бы неплохо поместить это в модель (что-то вроде @status.css_class), но это не относится к ней. Что делает большинство людей?

ржаной
источник

Ответы:

142

Я использую первый способ, но с немного более емким синтаксисом:

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

Хотя обычно вы должны представлять успех с помощью логического trueили числового идентификатора записи, а неудачу с помощью логического falseили nil. Таким образом, вы можете просто проверить свою переменную:

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

Вторая форма с использованием тернарного ?:оператора полезна, если вы хотите выбирать между двумя классами:

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

Наконец, вы можете использовать помощники тегов записи Rail, такие как div_for, которые автоматически установят ваш идентификатор и класс на основе предоставленной вами записи. Учитывая Personс идентификатором 47:

# <div id="person_47" class="person good">
<% div_for @person, class: (@success ? 'good' : 'bad') do %>
<% end %>
Meagar
источник
@Anurag, зацените api.rubyonrails.org/classes/ActionController/… . Довольно изящная штука.
maček
спасибо за ссылку @macek. это очень похоже на то, как я создаю элементы в MooTools :) аккуратно и аккуратно
Anurag
2
Лучший ответ: избегайте всего беспорядка и переключитесь на HAML .
meagar
2
Или, что еще лучше, в SLIM
Доктор Стрейнджлав
4
@ Доктор Стрейнджлав, не могли бы вы привести пример того, как SLIM или HAML будут более элегантно обрабатывать условные классы? А как насчет нескольких условных классов?
Брендон Мьюир,
18

Избегая логики во взглядах

Проблема стандартного подхода состоит в том, что он требует логики в форме ifоператоров или троек в представлении. Если у вас есть несколько условных классов CSS, смешанных с классами по умолчанию, вам необходимо поместить эту логику в интерполяцию строк или тег ERB.

Вот обновленный подход, который позволяет избежать какой-либо логики в представлениях:

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

class_string метод

class_stringПомощник принимает хэш с парами ключ / значение , состоящих из CSS строк имен классов и логических значений . Результатом метода является строка классов, в которых логическое значение оценивается как истина.

Пример использования

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

Другие варианты использования

Этот помощник можно использовать в ERBтегах или с помощниками Rails, такими как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 %>

Либо / или классы

Для случаев использования, когда потребуется тернар (например @success ? 'good' : 'bad'), передайте массив, где первый элемент - это класс, trueа другой - дляfalse

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

В духе React

Эта техника основана на надстройке, называемой classNames(ранее известной как classSet) от FacebookReact интерфейсной среды .

Использование в ваших проектах Rails

На данный момент этой class_namesфункции нет в Rails, но в этой статье показано, как добавить или реализовать ее в ваших проектах.

Карлос Рамирес III
источник
2

Вы также можете использовать помощник content_for, особенно если DOM находится в макете и вы хотите установить класс css в зависимости от частично загруженного.

По макету:

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

На частичном:

- content_for :css_class do
    my_specific_class

Вот и все.

Acmoune
источник