Apa cara yang elegan untuk menambahkan kelas secara bersyarat ke elemen HTML dalam tampilan?

103

Saya kadang-kadang harus menambahkan kelas ke elemen html berdasarkan suatu kondisi. Masalahnya adalah saya tidak dapat menemukan cara yang tepat untuk melakukannya. Inilah contoh dari hal-hal yang telah saya coba:

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

ATAU

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

Saya tidak suka pendekatan pertama karena tampilannya penuh sesak dan sulit dibaca. Saya tidak suka pendekatan kedua karena sarangnya kacau. Akan menyenangkan untuk memasukkannya ke dalam model, (sesuatu seperti @status.css_class), tapi itu bukan miliknya. Apa yang dilakukan kebanyakan orang?

ryeguy
sumber

Jawaban:

141

Saya menggunakan cara pertama, tetapi dengan sintaks yang sedikit lebih ringkas:

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

Meskipun biasanya Anda harus mewakili keberhasilan dengan boolean trueatau ID data numerik, dan kegagalan dengan boolean falseatau nil. Dengan cara ini Anda bisa menguji variabel Anda:

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

Formulir kedua yang menggunakan ?:operator terner berguna jika Anda ingin memilih di antara dua kelas:

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

Akhirnya, Anda dapat menggunakan bantuan tag catatan Rail seperti div_for, yang akan secara otomatis mengatur ID dan kelas Anda berdasarkan catatan yang Anda berikan. Diberikan Persondengan id 47:

# <div id="person_47" class="person good">
<% div_for @person, class: (@success ? 'good' : 'bad') do %>
<% end %>
meagar
sumber
@Anurag, lihat ini api.rubyonrails.org/classes/ActionController/… . Barang yang cukup rapi.
maček
terima kasih untuk tautannya @macek. ini sangat mirip dengan cara saya membuat elemen di MooTools :) rapi dan rapi
Anurag
2
Jawaban yang lebih baik: Hindari seluruh kekacauan dan alihkan pandangan Anda ke HAML .
meagar
2
Atau, lebih baik lagi, untuk SLIM
Dr. Strangelove
4
@ Dr.Strangelove, apakah Anda dapat memberikan contoh bagaimana SLIM atau HAML akan menangani kelas bersyarat dengan lebih elegan? Bagaimana dengan kasus kelas bersyarat ganda?
Brendon Muir
18

Menghindari logika dalam pandangan

Masalah dengan pendekatan standar adalah membutuhkan logika dalam bentuk ifpernyataan atau terner dalam tampilan. Jika Anda memiliki beberapa kelas CSS bersyarat yang dicampur dengan kelas default, maka Anda perlu memasukkan logika itu ke dalam interpolasi string atau tag ERB.

Berikut adalah pendekatan terbaru yang menghindari memasukkan logika apa pun ke dalam tampilan:

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

class_string metode

The class_stringhelper mengambil hash dengan pasangan kunci / nilai yang terdiri dari string nama kelas CSS dan nilai-nilai boolean . Hasil dari metode ini adalah string kelas di mana nilai boolean dievaluasi menjadi benar.

Penggunaan Sampel

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

Kasus Penggunaan Lainnya

Helper ini dapat digunakan di dalam ERBtag atau dengan pembantu Rails seperti 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 %>

Salah Satu / Atau Kelas

Untuk kasus penggunaan di mana terner akan diperlukan (misalnya @success ? 'good' : 'bad'), berikan larik di mana elemen pertama adalah kelasnya truedan yang lainnya untukfalse

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

Terinspirasi oleh React

Teknik ini terinspirasi oleh add-on yang disebut classNames(sebelumnya dikenal sebagai classSet) dari Reactkerangka front-end Facebook .

Menggunakan dalam proyek Rails Anda

Sampai sekarang, class_namesfungsinya tidak ada di Rails, tetapi artikel ini menunjukkan cara menambahkan atau mengimplementasikannya ke dalam proyek Anda.

Carlos Ramirez III
sumber
2

Anda juga bisa menggunakan helper content_for, terutama jika DOM terletak di layout dan Anda ingin menyetel kelas css bergantung pada pemuatan parsial.

Pada tata letak:

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

Secara parsial:

- content_for :css_class do
    my_specific_class

Hanya itu saja.

acmoune
sumber