🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Vuex

Vuexは、Vue.js アプリケーションのための状態管理ライブラリです。アプリケーション内で使用するコンポーネントのための集中データストアを提供。コンポーネント同士でデータをやり取りし、処理のフローを一貫させたり、データの見通しを良くすることができます。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

Q&A

解決済

1回答

1041閲覧

Vue.js+Rails で linkt_to 経由の画面遷移でVue.js で作った画面を表示したいです

yuki0920

総合スコア31

Vuex

Vuexは、Vue.js アプリケーションのための状態管理ライブラリです。アプリケーション内で使用するコンポーネントのための集中データストアを提供。コンポーネント同士でデータをやり取りし、処理のフローを一貫させたり、データの見通しを良くすることができます。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

0グッド

0クリップ

投稿2021/02/07 02:33

編集2021/02/07 02:38

概要

Rails のアプリケーションで問い合わせページを作成しております。Haml にエントリーポイントを作成し、 Vue コンポーネントを 表示しようとしていますが、この表示がうまくできず、解決したいです。

実現したいこと

該当の URL の ヘルパーパス を使ったリンク link_to ‘お問い合わせ’, contacts_path 経由でのアクセスだと、 Vue.js で作成したテンプレートが描画されないのですが、描画されるようにしたいです。

一方で、該当の URL は /contacts であり、開発環境の URL localhost:3000 に直接アクセスする、もしくはページを リロードすると Vue.js で作成したテンプレートが描画されます

なぜ、 link_to 経由の画面遷移の場合 Vue.js で作成したテンプレート が表示されないのか、どのようにすれば表示できるのかご教示いただけると幸いです。

表示されない時

イメージ説明

表示される時

イメージ説明

環境

$ sw_vers ProductName: macOS ProductVersion: 11.1 BuildVersion: 20C69

Gemfile

1# 一部 2ruby '3.0.0' 3gem 'rails', '6.1.1' 4gem 'webpacker'

確認したこと

1. ブラウザのコンソールにエラーは表示されていない

ブラウザの Dev Tools ではコンソールにエラーは表示されていないことを確認しました。

イメージ説明

2. サーバーのログにはエラーが表示されていない

サーバーのログにもエラーが表示されていないことを確認しました。

bash

1web_1 | Started GET "/contacts" for 172.18.0.1 at 2021-02-07 02:20:16 +0000 2web_1 | Processing by ContactsController#new as HTML 3web_1 | Rendering layout layouts/application.html.haml 4web_1 | Rendering contacts/new.html.haml within layouts/application 5web_1 | [Webpacker] Everything's up-to-date. Nothing to do 6web_1 | Rendered contacts/new.html.haml within layouts/application (Duration: 39.8ms | Allocations: 3453) 7web_1 | User Load (0.5ms) SELECT "users".* FROM "users" WHERE "users"."id" IS NULL LIMIT $1 [["LIMIT", 1]] 8web_1 | ↳ app/helpers/sessions_helper.rb:5:in `current_user' 9web_1 | CACHE User Load (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" IS NULL LIMIT $1 [["LIMIT", 1]] 10web_1 | ↳ app/helpers/sessions_helper.rb:5:in `current_user' 11web_1 | Rendered layouts/_navbar.html.haml (Duration: 16.0ms | Allocations: 1865) 12web_1 | Rendered layouts/_flash_messages.html.haml (Duration: 0.1ms | Allocations: 23) 13web_1 | Rendered layouts/_footer.html.haml (Duration: 0.2ms | Allocations: 199) 14web_1 | Rendered layout layouts/application.html.haml (Duration: 188.2ms | Allocations: 17986) 15web_1 | Completed 200 OK in 198ms (Views: 195.4ms | ActiveRecord: 0.5ms | Allocations: 18728) 16web_1 | 17web_1 |

ファイル群

詳細は GitHub - yuki0920/supplebox at debug_contact_vue に掲載しております。

app/controllers/contacts_controller.rb

1# app/controllers/contacts_controller.rb 2 3class ContactsController < ApplicationController 4 def new 5 render 'new' 6 end 7 8 def create 9 ... 10 end 11end

app/views/contacts/new.html.haml

1# app/views/contacts/new.html.haml 2= javascript_pack_tag 'contact_message', 'data-turbolinks-track': 'reload' 3 4#contact_message{'v-cloak': ''}

app/javascript/packs/contact_message.js

1# app/javascript/packs/contact_message.js 2 3import Vue from 'vue/dist/vue.esm' 4import ContactMessage from '../ContactMessage.vue' 5 6document.addEventListener('DOMContentLoaded', () => { 7 const app = new Vue({ 8 el: '#contact_message', 9 components: { ContactMessage }, 10 render: h => h(ContactMessage) 11 }) 12})

app/javascript/ContactMessage.vue

1 2# app/javascript/ContactMessage.vue 3 4<template> 5 <div class="contact"> 6 <h1>お問い合わせ</h1> 7 <p>お気軽にお問い合わせください!</p> 8 <ValidationObserver v-slot="{ handleSubmit }"> 9 <form @submit="handleSubmit(submitForm)"> 10 <div class="form-group row"> 11 <label for="contact_name" class="col-sm-3 col-form-label">お名前</label> 12 <ValidationProvider v-slot="{ errors }" rules="required" name="お名前" class="col-sm-9"> 13 <input v-model="formData.name" type="text" class="form-control" id="contact_name"> 14 <span class="error text-danger">{{ errors[0] }}</span> 15 </ValidationProvider> 16 </div> 17 <div class="form-group row"> 18 <label for="contact_email" class="col-sm-3 col-form-label">メールアドレス</label> 19 <ValidationProvider v-slot="{ errors }" rules="required|email" name="メールアドレス" class="col-sm-9"> 20 <input v-model="formData.email" type="email" class="form-control" id="contact_email"> 21 <span class="error text-danger">{{ errors[0] }}</span> 22 </ValidationProvider> 23 </div> 24 <div class="form-group row"> 25 <label for="contact_title" class="col-sm-3 col-form-label">タイトル</label> 26 <ValidationProvider v-slot="{ errors }" rules="required" name="タイトル" class="col-sm-9"> 27 <input v-model="formData.title" type="text" class="form-control" id="contact_title"> 28 <span class="error text-danger">{{ errors[0] }}</span> 29 </ValidationProvider> 30 </div> 31 <div class="form-group row"> 32 <label for="contact_content" class="col-sm-3 col-form-label">お問い合わせ内容</label> 33 <ValidationProvider v-slot="{ errors }" rules="required" name="お問い合わせ内容" class="col-sm-9"> 34 <textarea v-model="formData.content" class="form-control" id="contact_content" rows="3"></textarea> 35 <span class="error text-danger">{{ errors[0] }}</span> 36 </ValidationProvider> 37 </div> 38 39 <div class="form-group row justify-content-end"> 40 <div class="col-sm-9"> 41 <button type="submit" class="btn btn-success">送信する</button> 42 </div> 43 </div> 44 </form> 45 </ValidationObserver> 46 </div> 47</template> 48 49<script> 50import { extend, localize, ValidationObserver, ValidationProvider } from 'vee-validate' 51import { required, email } from 'vee-validate/dist/rules' 52import ja from 'vee-validate/dist/locale/ja.json' 53 54// バリデーションルール 55extend('required', required); 56extend('email', email); 57 58// メッセージのローカライズ 59localize('ja', ja); 60 61// axios 62import axios from 'axios' 63const addCsrfToken = () => { 64 axios.defaults.headers.common = { 65 "X-Requested-With": "XMLHttpRequest", 66 "X-CSRF-TOKEN": document 67 .querySelector('meta[name="csrf-token"]') 68 .getAttribute("content"), 69 } 70} 71export default { 72 components: { 73 ValidationObserver, 74 ValidationProvider 75 }, 76 mounted() { 77 addCsrfToken() 78 }, 79 data() { 80 return { 81 formData: { 82 name: "", 83 email: "", 84 title: "", 85 content: "" 86 } 87 } 88 }, 89 methods: { 90 submitForm() { 91 axios.post('/contacts', this.formData ) 92 } 93 } 94} 95</script> 96 97<style scoped> 98[v-cloak] { 99 display:none; 100} 101 102p { 103 font-size: 1em; 104 text-align: center; 105} 106</style>

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

自己解決

RailsにVue.jsを小さく導入する | count0.org を参考にさせていただき、自己解決できました。

結論、「Turbolinks」が原因でした。
Turbolinksのロードを待ってから、Vueインスタンスの生成を行う必要があることがわかりました。

エントリポイントのJavaScriptファイルを下記のように修正しました。

js

1document.addEventListener('turbolinks:load', () => { 2 if (document.getElementById('contact_message')) { 3 const app = new Vue({ 4 el: '#contact_message', 5 components: { ContactMessage }, 6 render: h => h(ContactMessage) 7 }) 8 } 9});

投稿2021/03/02 00:27

yuki0920

総合スコア31

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問