vue-js-modalを用いて投稿一覧ページにおいてRails × Vue.jsで動的なコンポーネントをモーダルウィンドウとして表示

投稿一覧ページから投稿詳細ページをモーダルウィンドウとして表示

![モーダルウィンドウ.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653881/ca85156e-903e-889c-7a1f-f46c8d87e01e.gif)

こんな感じの表示をする。

https://www.kabanoki.net/3144/
この記事を最初は参考にしてますが、動的な子コンポーネントを投稿一覧からモーダルウィンドウを表示させる技術は僕のオリジナルなので、動くは動きますが、なにか間違えてる可能性あります。
drinkをpostに置き換えて読めば読みやすいです。

投稿一覧ページRails と Vue.jsでSPAな感じにするやりかたはこちらの教材が結構参考になります。
てか今度僕が記事にできればなと思います。
https://www.techpit.jp/courses/123/curriculums/126/sections/935/parts/3581



# 下準備

```
npm install vue-js-modal --save
```
 vue-js-modalは簡単にモーダルウィンドウを簡単に実装できる
Vue.jsのライブラリ的なもの。


```hello_vue.js

import Vue from 'vue'
import App from '../app.vue'
+import VModal from 'vue-js-modal'
+Vue.use(VModal)
```

このように記述すれば下準備ok

#

```app/javascript/app.vue

<template>

        <li v-for="drink in drinks" :key="drink.id" class="list" >

                <span>{{ drink.price }}円<br>(税込み)</span>

                <button v-on:click="show(drink)">詳細を表示</button>
   
                <modal v-bind:name="'display-drink-'+drink.id"
                 height="1000px" 
                 styles="background-color: bisque">
                  <drinkShow :drink=drink></drinkShow>
                </modal>
        </li>



</div>
</template>

<script>

import axios from 'axios';
import likeButton from './packs/components/like/likeButton.vue';
import drinkShow from './packs/components/drinks/show.vue';


export default {
  components: {
      likeButton,
      drinkShow
  },
  data: function(){
    return {
      drinks: "drinks"
    }
  },
  mounted(){
    this.setDrink();
  },
  methods: {
    setDrink: function(){
      axios.get('/api/drinks')
      .then(response =>(
        this.drinks = response.data
      ))
    },
    show : function(drink) {
        this.$modal.show(`display-drink-${drink.id}`);
    },
    hide : function () {
      this.$modal.hide('display-drink-show');
    }
  }
}
</script>


```

以上が全体像

```js

 <button v-on:click="show(drink)">詳細を表示</button>
```

まずこんな感じに書いて、

```js
    show : function(drink) {
        this.$modal.show(`display-drink-${drink.id}`);
    },
```

show関数にdrinkという引数を渡してあげる。
this.$modal.show(`display-drink-${drink.id}`);
のthis.$modal.show引数に指定したものと、modal name=””
のnameに指定したものが一致したらそのモーダルウィンドウを開く仕様らしい。

```vue
 <modal v-bind:name="'display-drink-'+drink.id"
     　　height="1000px" 
        styles="background-color: bisque">
    <drinkShow :drink=drink></drinkShow>
 </modal>

```

一意性を持たせるために、drinkのidによってモーダルウィンドウを開くようにする。
やってもらったら分かると思いますが、this.$modal.show("hoge");
 <modal name="hoge">
とやったら、配列の中にmodalを置いているので、配列分ループされて、配列分モーダルウィンドウが表示されてしまう。
なので、drink.idでnameを指定することにより、一意性を持たせて、ボタンを押したら
その押した投稿した表示されないようにする。
このやり方は俺が自分で考えた。まじで天才すぎる。

```vue
 <modal v-bind:name="'display-drink-'+drink.id"
     　　height="1000px" 
        styles="background-color: bisque">
    <drinkShow :drink=drink></drinkShow>
 </modal>

```

こんな感じでスタイルを指定したり、
modalの中に子コンポーネントを配置してる。
んで、子コンポーネントのタグにこんな感じで書くことで
子コンポーネントにデータを渡してる。



```javascript/packs/conponents/drinks/show.vue

<template>

<div class='show-main'>


        <div class='item-img-content'>
          <button v-on:click="hide(drink)">戻る</button>

          <img class= "item-img" v-bind:src="drink.image" >
        </div>
        <div class='item-info'>
          <h3 class='item-name'>
            {{drink.name}} 
          </h3>
          <div class='item-price'>
            <span>{{drink.price}}円<br>(税込み)</span>
          </div>
          <div class='item-explain'>
             {{drink.explain}}
          </div>


    </ul>


</div>

</template>

<script>

export default {
  props: ['drink'],
  components: {
      // likeButton
  },
  methods: {
    hide : function (drink) {
      this.$modal.hide(`display-drink-${drink.id}`);
    }
  }
}

</script>


```


  props: ['drink'],

と書くことで親コンポーネントから送られたデータを受け取れる。
まぁあとは見たとおり。

投稿一覧からモーダルウィンドウを表示するのは割と工夫が必要でしたが、
これでできました。