投稿一覧ページから投稿詳細ページをモーダルウィンドウとして表示
こんな感じの表示をする。
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のライブラリ的なもの。
import Vue from 'vue'
import App from '../app.vue'
+import VModal from 'vue-js-modal'
+Vue.use(VModal)
このように記述すれば下準備ok
<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の中に子コンポーネントを配置してる。
んで、子コンポーネントのタグにこんな感じで書くことで
子コンポーネントにデータを渡してる。
<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'],
と書くことで親コンポーネントから送られたデータを受け取れる。
まぁあとは見たとおり。
投稿一覧からモーダルウィンドウを表示するのは割と工夫が必要でしたが、
これでできました。