画像のように、一覧画面で詳細を開く
ボタンで詳細画面を開くときに、Railsのviewは使用せずVue.jsのModalで表示することを試みた。
何とか実装出来たが、JSはjQueryから入門したこともあり結構大変だったのでメモとして残しておく。
環境
Ruby 2.6.5
Ruby on Rails 6.0.0
Vue.js 2.6.11
ここではRailsやVueの設定は省略し、Railsのwebpackerでvueのインストール、セットアップが完了していることを前提として書いていく。
やりたい事
冒頭の通り、詳細を開く
ボタンをクリックしたときに詳細画面をVue.jsのModalで開きたい。
しかし、今までRailsの中でVueを使った事はあっても、Vueインスタンスがどのタイミングで生成されるかなど無知であったため、最初はどうやるのかイメージがつかなかった。
jQueryからJavascriptに入門したので、なかなか生のJSを書く機会がなかった。
Rails側
Modalを開く部分はBootstrapを使うことにした。
参照: https://getbootstrap.com/docs/4.0/components/modal/
上記のURLを参考にして、BootstrapだけでModalを開けるようにしていく。
view/users/index.html.slim
thead
tr
th id
th 名前
th email
th tell
th
tbody
- @users.each do |user|
tr
th = user.id
td = user.name
td = user.email
td = user.tell
td
/ Vue側にuser_idを渡すために、data属性にuser_idを持たせている
button.btn.btn-info.btn-modal data-target="#full-width-modal" data-toggle="modal" data-user_id="#{user.id}" 詳細を開く
/ Modalのコンポーネント部分。ここにVueのtemplateをマウントさせる。
#full-width-modal.modal.fade tabindex="-1" role="dialog" aria-hidden="true" aria-labelledby="full-width-modalLabel" data-keyboard="false" data-backdrop="static"
#showUser
= javascript_pack_tag 'users'
Vue.js側
次にvueインスタンスを生成させていく。
javascript/packs配下にusers.js
を作成し、コードを記述
javascript/packs/users.js
import Vue from 'vue'
// packs配下にcomponentsディレクトリを作成し、その中にcomponentを格納している
import ShowUser from './components/ShowUser.vue'
// ボタン要素をgetElementsByClassNameで配列として取得
const btnModals = document.getElementsByClassName('btn-modal')
// for文で各ボタン要素を取り出し
for(let btnModal of btnModals) {
// 取り出したボタン要素に対し、addEventListenerでボタンクリックされた時にvueインスタンスを生成させる
btnModal.addEventListener('click', () => {
new Vue({
el: '#showUser',
render: h => h(
ShowUser, {
// componentにpropsでuser_idを渡している
props: {
userId: Number(btnModal.getAttribute('data-user_id'))
}
}
)
})
})
}
ここまで出来たら、あとはShowUser.vue
を書いていけば終わり。
Modalを閉じるときはどうすればいいの?となりそうだが、単純に閉じるボタンのアクションにthis.$destroy()
を仕込んであげれば大丈夫。
modalを閉じる処理をbootstrapのjQueryではなく、Vue側で書いてあげないといけないので、そこも含めて次回の記事で頑張って書いていく。