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

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

詳細はこちら
Ruby on Rails 6

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

Ruby on Rails

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

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

1回答

1733閲覧

RubyonRailsのjsファイル上で部分テンプレートを挿入する方法

kirsche

総合スコア1

Ruby on Rails 6

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

Ruby on Rails

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

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

0クリップ

投稿2020/12/01 09:16

編集2020/12/02 03:50

前提・実現したいこと

質問ページをご覧いただきましてありがとうございます!

現在RubyonRailsで利用ユーザーが部屋を作成して、作成された部屋を一覧表示する機能を非同期通信で行うべく、JavascriptでAjaxを利用して実装しております。
流れとしては

①ページ上のルーム作成ボタンをクリック
②モーダルウィンドウ上に部屋名と部屋説明を入力するフォームと、作成・キャンセルボタンが表示される。
③フォームに情報を記入後、作成ボタンを押すことでClickイベントが発火し、フォーム内容がRailsの該当コントローラーのCreateアクションへ送信される。
④Createアクション内でフォーム内容をデータベースに登録し、レスポンスを返します。

ここまでの流れは実装済みであり、作成した部屋はリロードを行うことで一覧に表示される仕組みになっています。

発生している問題・エラーメッセージ

上記の④から、現状はjavascript上でlocation.reload();にて強制的にリロードをかけることで一覧表示を更新している状態です。
この部分をinsertAdjacentHTMLを使って、レスポンスの情報を元に追加したルーム部分を部分テンプレート化して、この部分テンプレートを挿入して表示させようとしております。(以下のような感じです)

javascript

1document.getElementById('挿入部分のid').insertAdjacentHTML('beforeend', '<%= render "部分テンプレート名" %>')

ただ当然Javascript上なので、<%= render %>部分は認識されず、文字としてそのまま挿入される状態です。
色々検索をかけてescape_javascriptなどのエスケープを試してみてもダメで、実装方法に詰まっている状態です。
ですので、Javascript上で部分テンプレートを指定する方法や代替案などがあればご教授頂けますと幸いです。

該当のソースコード

html

1(部屋一覧表示部分抜粋) 2<div class="room-screen-box"> 3 <div class="room-screen-lists"> 4 5 <% @rooms.each do |room| %> 6 <div class="room-screen-list-box"> 7 <div class="room-screen-list-header"> 8 <div class="room-screen-list-room-name"><%= link_to room.room_name,"#" %></div> 9 <div class="room-screen-list-btn"> 10 <% unless RoomUser.where(room_id: room.id).exists?(user_id: current_user.id) %> 11 <%= form_with model: @roomuser, local: true do |f| %> 12 <input name="room_user[user_id]" type="hidden" value=<%= current_user.id %>> 13 <input name="room_user[room_id]" type="hidden" value=<%= room.id %>> 14 <%= f.submit "参加", class:"room-entry-btn" %> 15 <% end %> 16 <% else %> 17 <div class="room-exist-btn"> 18 <%= link_to "退出", room_user_path(room), method: :delete %> 19 </div> 20 <% end %> 21 <% if room.owner_id == current_user.id %> 22 <div class="room-delete-btn"> 23 <%= link_to "削除", room_path(room), method: :delete, data: { confirm: '本当に削除しても良いですか?' } %> 24 </div> 25 <% end %> 26 </div> 27 </div> 28 <div class="room-screen-list-body"> 29 <div class="room-screen-list-owner-name">オーナー名:<%= User.find(room.owner_id).nickname %></div> 30 <div class="room-screen-list-create-date">作成日時:<%= room.created_at.to_s(:datetime_jp) %></div> 31 </div> 32 </div> 33 <% end %> 34 35 </div> 36</div>

html

1(モーダルウィンドウ部分抜粋) 2<div id="modal-room-create" class="modal-room-create"> 3 <p>ルームの作成</p> 4 <%= form_with model: @room, id: 'modal-room-create-form', local: true do |f| %> 5 <%= render "devise/shared/error_messages", model: f.object %> 6 <div class="field"> 7 <label class="form-text">ルーム名</label> 8 <%= f.text_field :room_name, placeholder:"ルーム名 (20文字以内)", maxlength:"20", class:"form-default" %> 9 </div> 10 11 <div class="field"> 12 <label class="form-text">ルーム説明文</label> 13 <%= f.text_field :room_description, placeholder:"ルーム説明 (100文字以内)", maxlength:"100", class:"form-default" %> 14 </div> 15 16 <input name="room[user_ids][]" type="hidden" value=<%= current_user.id %>> 17 18 <div class="register-btn"> 19 <%= f.submit "作成", class:"register-blue-btn", id:"modal-create-btn" %> 20 </div> 21 <% end %> 22 <button class="register-blue-btn" id="room-create-cancel">キャンセル</button> 23 24</div> 25 26<div id="modal-overlay" class="modal-overlay"></div>

html

1(挿入したい部分テンプレート) 2<div class="room-screen-list-box"> 3 <div class="room-screen-list-header"> 4 <div class="room-screen-list-room-name"><%= link_to room.room_name, room_posts_path(room) %></div> 5 <div class="room-screen-list-btn"> 6 <% unless RoomUser.where(room_id: room.id).exists?(user_id: current_user.id) %> 7 <%= form_with model: @roomuser, local: true do |f| %> 8 <input name="room_user[user_id]" type="hidden" value=<%= current_user.id %>> 9 <input name="room_user[room_id]" type="hidden" value=<%= room.id %>> 10 <%= f.submit "参加", class:"room-entry-btn" %> 11 <% end %> 12 <% else %> 13 <div class="room-exist-btn"> 14 <%= link_to "退出", room_user_path(room), method: :delete %> 15 </div> 16 <% end %> 17 <% if room.owner_id == current_user.id %> 18 <div class="room-delete-btn"> 19 <%= link_to "削除", room_path(room), method: :delete, data: { confirm: '本当に削除しても良いですか?' } %> 20 </div> 21 <% end %> 22 </div> 23 </div> 24 <div class="room-screen-list-body"> 25 <div class="room-screen-list-owner-name">オーナー名:<%= User.find(room.owner_id).nickname %></div> 26 <div class="room-screen-list-create-date">作成日時:<%= room.created_at.to_s(:datetime_jp) %></div> 27 </div> 28</div>

javascript

1(モーダルウィンドウの表示及び部屋作成時の挙動部分抜粋) 2window.addEventListener('load', function(){ 3 4 const modalRoomCreate = document.getElementById("modal-room-create") 5 const modalOverlay = document.getElementById("modal-overlay") 6 const roomCreateBtn = document.getElementById("room-create-btn") 7 const modalCreateBtn = document.getElementById("modal-create-btn") 8 const modalRoomCancel = document.getElementById('room-create-cancel'); 9 10 roomCreateBtn.addEventListener('click', function() { 11 modalRoomCreate.classList.add("active") 12 modalOverlay.classList.add("active") 13 }) 14 15 modalCreateBtn.addEventListener('click', function(e) { 16 e.preventDefault(); 17 18 const formData = new FormData(document.getElementById("modal-room-create-form")) 19 const XHR = new XMLHttpRequest(); 20 XHR.open("POST", `/rooms`, true) 21 XHR.responseType = "json"; 22 XHR.send(formData); 23 24 XHR.onload = () => { 25 document.getElementById("modal-room-create-form").reset(); 26 if (XHR.status == 422) { 27 alert(`入力項目エラー: ルーム作成のフォームは全て入力してください。`); 28 return null; 29 } 30 else if (XHR.status != 200) { 31 alert(`Error ${XHR.status}: ${XHR.statusText}`); 32 return null; 33 } 34 35 document.getElementById("modal-room-create-form").reset(); 36 modalRoomCreate.classList.remove("active") 37 modalOverlay.classList.remove("active") 38 39 location.reload(); 40 }) 41 42 modalRoomCancel.addEventListener('click', function() { 43 document.getElementById("modal-room-create-form").reset(); 44 modalRoomCreate.classList.remove("active") 45 modalOverlay.classList.remove("active") 46 }) 47 modalOverlay.addEventListener('click', function() { 48 document.getElementById("modal-room-create-form").reset(); 49 modalRoomCreate.classList.remove("active") 50 modalOverlay.classList.remove("active") 51 }) 52})

RubyonRails

1(コントローラー部分抜粋) 2class RoomsController < ApplicationController 3 def index 4 @rooms = Room.all.order(created_at: "DESC") 5 @room = Room.new 6 @roomuser = RoomUser.new 7 end 8 9 def create 10 @room = Room.new(room_params) 11 if @room.save 12 render json: { post: @room } 13 else 14 render json: { post: @room }, status: 422 15 end 16 end 17 18 def search 19 @rooms = Room.search(params[:keyword]) 20 end 21 22 def destroy 23 room = Room.find(params[:id]) 24 room.destroy 25 redirect_to root_path 26 end 27 28 private 29 30 def room_params 31 params.require(:room).permit(:room_name, :room_description, user_ids: []).merge(owner_id: current_user.id) 32 end 33 34end

補足情報(FW/ツールのバージョンなど)

Ruby on Rails6

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

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

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

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

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

guest

回答1

0

ベストアンサー

コントローラ側にてAjaxの返却値をその部分テンプレート(layout false)で返して.insertAdjacentHTML()で追記すれば良いのではないでしょうか。

投稿2020/12/01 13:35

m.ts10806

総合スコア80875

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

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

kirsche

2020/12/02 04:03

ご回答頂きましてありがとうございます! 頂いたご回答を元にもう一度調べ直しているところであります。 勉強不足で大変申し訳ないのですが、 render layout: falseについては調べて理解させて頂いたのですが こちらをAjaxの返却値(render json:)としてテンプレートを含めて返し insertAdjacentHTMLにてどう追記するのかがまだ理解が追いついていない状態です。 引き続きもう一度調べさせて頂きたいと思います!
m.ts10806

2020/12/02 04:11

jsonで返すとJavaScriptによるhtml生成が必要になりますし、テンプレートhtmlも使えません。それにJavaScriptによるhtmlレンダリングは高負荷です。 それなら全て値も埋め込まれたテンプレートhtmlそのものをサーバーから返してそのままinsertAdjacentHTML(追記ではなく上書きならinnerHTMLでもいいと思うけど)に突っ込んだら簡単だし、役割分担にもなるのではと。 私も言語限らずよくやります。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問