技術備忘録

環境構築によるトラブルの解決方法、知った技術のまとめなどを自分のためにも書き連ねていきます。あわよくば誰かの参考になればと思います。

Rails x Vue.jsで複数アコーディオンの実装

ほぼ一年ぶりのブログです。最近アウトプットが疎かになってる...

今回は、RailsとVue.jsを使った複数アコーディオンの実装を行います。

今回用いている環境

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を引数として渡しています。ユニークであれば productid でも構いません。)

toggleでは、 this.$set(this.show , key, !this.show[key]) ボタンをクリックした時に値を反転させることで、アコーディオンの開き閉じが出来るようになります。この時、showに存在しないkey(show[key])の場合は undefined が返ってくるのですが、jsの仕様上 undefined を反転させると true になるので true, false のフラグ切り替えが先程の1行で行うことができます。

後は、押した時に表示させたいコンテンツに v-show="show[<%= idx %>]" のようにデータを参照させることで複数箇所でのアコーディオンになります。

動作

f:id:isoflabon:20181225191303g:plain
accordion.gif

最後に

Vue.jsでの複数アコーディオンで調べた際に、配列での実装は検索で出てきたのですが連想配列で行う場合はあまりなかったので今回記事にしました。(調べ方が下手で引っかからなかっただけかもしれません。)