New to Rails 6.1 is a method called class_names
, from the ActionView::Helpers::TagHelper
module. This handy new view helper brings one of may favorite features from Vue.js to Rails.
In Vue.js (or React via the classnames library) we can do something like this:
<div class="{item: true, item__complete: item.complete, item__over_due: !item.complete && item.overDue }">
{{ item.name }}
</div>
Which, assuming we have the proper css classes and item object, will give us something like this:
<!-- item.complete == false -->
<div class="item">Incomplete Item</div>
<!-- item.complete == false && item.overDue == true -->
<div class="item item__over_due">Incomplete Item</div>
<!-- item.complete == true && item.overDue == true -->
<div class="item item__complete">Complete Item</div>
Obviously this is an overly simplified example but you get the idea. To do the same thing in Rails used to require something like this:
<%= tag.div class: "item #{item.completed? ? 'item__complete' : ''} #{!item.completed? && item.over_due? ? 'item__over_due' : ''}" do %>
<%= item.name %>
<% end %>
However, the introduction of class_names
simplifies this and makes it work very similarly to Vue. Now we can do something like this:
<%= tag.div class: class_names(item: true, item__complete: item.completed?, item__over_due: !item.completed? && item.over_due?) do %>
<%= item.name %>
<% end %>
Additionally, class_names
can take mixed argument types so the above could also be done as:
<%= tag.div class: class_names("item", { item__complete: item.completed?, item__over_due: !item.completed? && item.over_due? }) do %>
<%= item.name %>
<% end %>
NOTE: The above example explicitly calls class_names
for illustrative purposes. The tag
(and content_tag
) method uses class_names
under the hood already so the above can actually be done like this:
<%= tag.div class: ["item", { item__complete: item.completed?, item__over_due: !item.completed? && item.over_due? }] do %>
<%= item.name %>
<% end %>
I like this a lot and it will make building more complex conditional css class lists in Rails so much easier and cleaner. class_names
is an alias of token list
and you can view its documentation here.
Top comments (1)
also link_to seems to use class_name under the hood
<%= link_to "whatever", #", class: ["flex flex-ycenter", active: true] %>