概要
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>
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。