LoginSignup
1
2

More than 1 year has passed since last update.

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

Last updated at Posted at 2021-08-27

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

モーダルウィンドウ.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>


以上が全体像


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

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

    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に指定したものが一致したらそのモーダルウィンドウを開く仕様らしい。

 <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を置いているので、配列分ループされて、配列分モーダルウィンドウが表示されてしまう。
なので、drink.idでnameを指定することにより、一意性を持たせて、ボタンを押したら
その押した投稿した表示されないようにする。
このやり方は俺が自分で考えた。まじで天才すぎる。

 <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'],

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

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

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2