投稿一覧画面でタブ表示 (CSSで設定)
投稿一覧表示画面でタブ表示を実装します。
このように表示されます。
タブに表示されている文字「ドッグラン」〜「他」はカテゴリー名です。
カテゴリーは、(管理者により)あらかじめ用意されているものから投稿時に選択します。
この一覧画面では、カテゴリー別に自動で振り分けられています。
それでは記述方法を見ていきましょう。
記述するファイル
・posts_controller.rb
・posts/index.html
・posts/_index.html
・posts/_map_index.html
・app/javascript/packs/application.css
コードは以下のように書きました。
posts/index.html.erb
<!--tab表示-->
<div class="wrapper">
<ul class="tab-menu">
<li class="<%= 'active' unless @category %>"><%= link_to '全て', posts_path %></li>
<!--タブに表示されたカテゴリー名に紐づく投稿を一覧表示-->
<% @categories.each do |category| %>
<li class="<%= 'active' if category == @category %>"><%= link_to category.name, posts_path(category: category.name) %></li>
<% end %>
</ul>
<div class="tab-contents">
<div class="tab-area is-active">
<div class="row">
<!--一覧-->
<div class="col-md-8">
<%= render 'index', posts: @posts %>
<div class="row justify-content-center my-2">
<%= paginate @posts %>
</div>
</div>
<div class="col-md-4">
<%= render 'map_index', posts: @posts %>
</div>
</div>
<!--Top-pageリンク-->
<p id="page-top"><a href="#">Page Top</a></p>
</div>
</div>
</div>
タブ表示のタブ部分を作成するコードを確認します。
①
<ul> <li>リスト名</li> <ul>
でリストを作成
② リスト(タブ)はCSSで横並びにする
③ カテゴリー名を取得してリスト名(タブ名)として表示する
④ タブを選択するとカテゴリーに紐づく投稿一覧を表示する
リスト名 = タブに表示される名称 = カテゴリー名 です。
<ul class="tab-menu">
<li class="<%= 'active' unless @category %>"><%= link_to '全て', posts_path %></li>
<% @categories.each do |category| %>
<li class="<%= 'active' if category == @category %>"><%= link_to category.name, posts_path(category: category.name) %></li>
<% end %>
</ul>
ここに、<li class="<%= 'active' ... %>"></li>
というコードが2つあります。
これはif文の条件次第で'active'クラスが付くということです。
(if文の結果がfalseであれば、'active'クラスは付かない)
1つ目
<li class="<%= 'active' unless @category %>"><%= link_to '全て', posts_path %></li>
-
全て
タブに関するコードです。
@category はコントローラで定義されています。
def index
@categories = Category.all
# タブ表示(カテゴリー別or全件)
if params[:category]
@category = Category.find_by(name: params[:category])
@posts = @category.posts
else
@posts = Post.all
end
end
カテゴリータブを選択している場合、
そのカテゴリー名をもとにデータベースからcategoriesテーブルのレコードを取得し、@categoryに代入します。
レコードを取得できない場合(存在しない場合)はnilが代入されます。取得できない場合とは、'全て'タブを選択している時です。
つまりこの場合、@category = nil → 全て の場合に 'active' クラスが付きます。
<%= link_to '全て', posts_path %>
これはposts_path(投稿一覧)へのリンクで、タブには ’全て’ と表示されます。
’全て’ というタブが選択されているとき、投稿一覧(全件)が表示されます。
2つ目
<li class="<%= 'active' if category == @category %>"><%= link_to category.name, posts_path(category: category.name) %></li>
-
カテゴリー名
タブに関する記述です。
コントローラに定義しているように、@categoriesからeach文でデータベースよりカテゴリーのデータを一つ一つ取得しタブに表示します。
if category == @category
ですが、選択されているカテゴリーのデータが取得できた場合(nilでない場合)に 'active' クラスが付きます。
<%= link_to category.name, posts_path(category: category.name) %>
同じくposts_path(投稿一覧)へのリンクですが、そのカテゴリーに紐づく投稿のみ表示されます。
タブには 'カテゴリー名' が表示されます。
posts/_index.html.erb
<div class="row">
<% posts.each do |post| %>
<div class="card-deck ml-1 my-2">
<div class="card border-secondary bg-light" style="width: 10rem">
<div class="card-img-top">
<%= image_tag post.get_post_image, height: '120', width: '100%' %>
</div>
<div class="card-body">
<%= link_to post_path(post), class: 'link' do %>
<h6 class="card-title border-bottom"><b><%= post.name.truncate(14) %></b></h6>
<% end %>
<small>
<div class="card-text"><%= post.introduction.truncate(18) %></div>
</small>
</div>
<div class="card-footer bg-light">
<small>
<div class="card-text">所在地: <%= post.prefecture %></div>
<% if member_signed_in? %>
<div class="card-btn-area card-text">
<div class="card-btn favorite-btn_<%= post.id %>">
<%= render 'public/favorites/favorite_btn', post: post %>
</div>
<div class="card-btn interest-btn_<%= post.id %>">
<%= render 'public/interests/interest_btn', post: post %>
</div>
<div class="card-btn">
<i class="far fa-comment-dots"></i> <%= post.comments.count %>
</div>
</div>
<% end %>
<div class="card-text">投稿者: <%= post.member.nickname %></div>
<div class="card-text">投稿日: <%= l post.created_at %></div>
</small>
</div>
</div>
</div>
<% end %>
</div>
タブの下に表示される投稿一覧は、部分テンプレートにまとめています。
私はbootstrapのcardで表示していますが、ここは表示したいように変更してください。
タブ表示の設定をCSSに記述
app/javascript/packs/application.css
.wrapper {
width: 100%;
margin: 0 auto;
}
.tab-menu {
display: flex;
margin: 0;
}
.tab-menu li {
list-style-type: none;
width: 25%;
}
.tab-menu li a {
color: #2e1212;
text-decoration: none;
display: block;
margin: 0 5px;
padding: 10px 10px;
text-align: center;
background: #f9f9f9;
}
.tab-menu li a:hover {
font-weight: bolder;
}
.tab-menu li.active a {
background: #F9F5EB;
color: #2e1212;
}
.tab-contents {
display: flex;
justify-content: center;
}
.tab-area {
display: none;/*はじめは非表示*/
opacity: 0;/*透過0*/
background: #F9F5EB;
padding: 50px 20px;
width: 100%;
}
.tab-area.is-active {
display: block;/*選択されたら表示*/
animation-name: displayAnime;/*ふわっと表示させるためのアニメーション*/
animation-duration: 2s;
animation-fill-mode: forwards;
}
@keyframes displayAnime{
from {
opacity: 0;
}
to {
opacity: 1;
}
}
CSSについて
.wrapper
タブ表示による全体部分。横幅指定。
.tab-menu
タブの部分。flex指定により、横並びに。
.tab-menu li
各タブの文字の設定。<li>による ’・’ は非表示に。
.tab-menu li a
a はリンクになっているタブの文字部分。リンクの下線、文字の色、背景色、余白等の設定。
.tab-menu li a:hover
タブの文字にカーソルを合わせている時、文字を太字に。
.tab-menu li.active a
activeクラスがついているタブ(選択されているタブ)は色を変える。
.tab-contents
タブに対応する一覧表示範囲の設定。
.tab-area
各タブに紐づく一覧表示部分。デフォルトとして非表示に設定。
.tab-area.is-active
タブにactiveクラスの付いた一覧表示部分。デフォルトとして非表示から、クラスが付くと一覧をふわっと表示させる。
@keyframes displayAnime
非表示からふわっと表示させるアニメーション。.tab-area.is-active
の ”animation-name: displayAnime;” と紐づく。
これでカテゴリーとタブが紐づき、それぞれの一覧が表示されるはずです。
以上です。
Discussion
すごい!うまくまとめてられてる!!
CSSの命名規則で、BEMというものもある!!!
自分のまとめはこのようにしたけど(今見たらわかりずらいから修正するか..!)
よく使われる命名規則でもあるのでみてみると面白いと思う!✨
ありがとです!
BEMってちゃんと考えられたことないかも。。
もっとよく調べて勉強する!😊