Rails x Vue.jsで複数アコーディオンの実装
ほぼ一年ぶりのブログです。最近アウトプットが疎かになってる...
今回は、RailsとVue.jsを使った複数アコーディオンの実装を行います。
今回用いている環境
- Rails 5.2.1
- Vue 2.x
vueはwebpackを使って管理しています。
前提
店舗(store)は複数の商品(product)を取り扱っているとします。
Model
Store
name
product_id
Product
name
price
comment
上記のような状況を想定します。 今回は店舗詳細画面をイメージして、商品の名前を押すと価格とコメントが表示されるようにします。
コード・説明
viewにはerbを使っています。
show.html.erb
<div id="app"> <%= @store.products.each_with_index do |product, idx| %> <div class="card border-primary"> <div @click="toggle(<%= idx %>)" class="card-header"> <%= product.name %> </div> <div v-show="show[<%= idx %>]" class="card-body"> <p>価格: <%= product.price %></p> <p>一言コメント: <%= product.comment %></p> </div </div> <% end %> </div> <%= javascript_pack_tag 'store_show' %>
store_show.js
import Vue from "vue"; const vm = new Vue({ el: "#app", data: { show: {} }, methods: { toggle: function (key) { this.$set(this.show , key, !this.show[key]) } } });
toggle
はjsで定義しています。ポイントとしては toggle
の引数にユニークな値を渡してあげることです。(ここでは、ループのindexを引数として渡しています。ユニークであれば product
の id
でも構いません。)
toggleでは、 this.$set(this.show , key, !this.show[key])
ボタンをクリックした時に値を反転させることで、アコーディオンの開き閉じが出来るようになります。この時、showに存在しないkey(show[key])の場合は undefined
が返ってくるのですが、jsの仕様上 undefined
を反転させると true
になるので true, false のフラグ切り替えが先程の1行で行うことができます。
後は、押した時に表示させたいコンテンツに v-show="show[<%= idx %>]"
のようにデータを参照させることで複数箇所でのアコーディオンになります。
動作
最後に
Vue.jsでの複数アコーディオンで調べた際に、配列での実装は検索で出てきたのですが連想配列で行う場合はあまりなかったので今回記事にしました。(調べ方が下手で引っかからなかっただけかもしれません。)