解決したいこと
raisで実装中のチャットアプリにて、相互フォローユーザ間で作られた1対1のトークルームにおけるメッセージのやり取りを非同期通信にしたいと思い実装を行ったのですが、現状では下記の画像のようにメッセージ送信後、画面遷移が行われてしまいます。
①【url: rooms/[:id]のチャットページにて、メッセージを入力し、送信ボタンを押すと...】
②【url: messagesのページへ移り、保存された情報が表示されてしまう。】
記述したrubyのコード(messages_controller.rb)
ruby
1 def create 2 if Entry.where(user_id: current_user.id, room_id: params[:message][:room_id]).present? 3 message = Message.create(message_params) 4 render json:{ message: message } 5 else 6 flash[:alert] = "メッセージ送信に失敗しました。" 7 end 8 end 9 10 private 11 def message_params 12 params.require(:message).permit(:content, :user_id, :room_id).merge(user_id: current_user.id) 13 end
記述したJavaScriptコード(message.js)
javascript
1function chat() { 2 const submit = document.getElementById("submit"); 3 submit.addEventListener("click", (e) => { 4 5 e.preventDefault(); 6 const formData = new FormData(document.getElementById("form")); 7 const XHR = new XMLHttpRequest(); 8 XHR.open("POST", "/messages", true); 9 XHR.responseType = "json"; 10 XHR.send(formData); 11 XHR.onload = () => { 12 if (XHR.status != 200){ 13 alert(`Error ${XHR.status}: ${XHR.statusText}`); 14 return null; 15 } 16 const item = XHR.response.message; 17 const list = document.getElementById("list") 18 const formText = document.getElementById("content-message") 19 const HTML = ` 20 <div class="chat-box"> 21 <div class="chat-face"> 22 if (${message.user.avatar}.attached?){ 23 <img src="${message.user.avatar}", class="icon-image-mini"> 24 } 25 </div> 26 <div class="chat-message"><strong>${message.content}</strong><br> 27 l ${message.created_at} 28 </div> 29 </div> 30 `; 31 list.insertAdjacentHTML("afterend", HTML); 32 formText.value = ""; 33 }; 34 }); 35} 36 37window.addEventListener("load", chat);
記述したHTMLビューファイル
html
1<div class="messages", id="message"> 2 <div class="chat-header"> 3 <div class="left-button"> 4 <%= link_to '〇〇さんとのチャットルーム', root_path %> 5 </div> 6 <div class="room-exit"><%= link_to 'トップページに戻る', root_path %></div> 7 </div> 8 <% @entries.each do |e| %> 9 <div class="user-name"> 10 <strong> 11 <% if e.user.avatar.attached? %> 12 <%= image_tag e.user.avatar, class:"icon-image" %> 13 <% end %> 14 <a class="room-user-link" href="/users/<%= e.user.id %>"> 15 <%= e.user.name%>さん 16 </a> 17 </strong> 18 </div> 19 <% end %> 20 <hr> 21 <div class="chats"> 22 <div class="chat"> 23 <% if @messages.present? %> 24 <% @messages.each do |m| %> 25 <div class="chat-box"> 26 <div class="chat-face"> 27 <% if m.user.avatar.attached? %> 28 <%= image_tag m.user.avatar, class:"icon-image-mini" %> 29 <% end %> 30 </div> 31 <div class="chat-message"><strong><%= m.content %></strong><br> 32 <%= l m.created_at %> 33 </div> 34 </div> 35 <% end %> 36 <% end %> 37 <div id="list" ></div> 38 </div> 39 </div> 40</div> 41<div id="chat"> 42<span id="video-end">ビデオ通話を止める</span> 43 <chat /> 44</div> 45<%= javascript_pack_tag 'chat' %> 46<%= stylesheet_pack_tag 'chat' %> 47<div class="form"> 48 <%= form_for @message, id: "form", class: "post" do |f| %> 49 <div class="post-message"> 50 <%= f.text_field :content, placeholder: "メッセージを入力してください", size: 70, class:"form-text-field", id:"content-message" %> 51 <%= f.hidden_field :room_id, value: @room.id %> 52 <%= f.submit '送信', class:"form-submit", id: "submit" %> 53 <input type="button" value="ビデオ通話を始める", class="form-submit", id= "video-button"> 54 </div> 55 <% end %> 56</div>
生じているconsoleエラー
message.js:4 Uncaught TypeError: Failed to construct 'FormData': parameter 1 is not of type 'HTMLFormElement'. at HTMLInputElement.<anonymous> (message.js:4)
試したこと
DBには送信した内容が正しく保存されていたことから、通常のcreateアクションが働いてしまっているため、上記のような挙動になっているのかと思い、e.preventDefault();を追加しました。が、追加した場所が悪いのか挙動に変化はありませんでした。
また、messageの保存作業がmessageコントローラーのcreateアクションで行われているのに対して、保存したメッセージの表示場所をroomsコントローラーのindexのshowアクションに設定していることが原因かとも考えましたが、具体的な解決策は浮かびませんでした。
稚拙な質問で申し訳ありませんが、ご回答頂けると幸いです。
その他、補足情報
Mac OS Catalina 10.15.4
ruby 2.6系
rails 6.0系
を使っております。
また、message.jsファイルはapplication.jsに読み込み済みです。