Bootstrapでモーダルを使用した投稿機能を実装したので編集もモーダルで編集したかったので実装してみた
Bootstrap5とJQueryはCDNで読み込んでいる。
コントローラーは通常通り記述
def index
@recipes = Recipe.all
@recipe = Recipe.new
end
def create
Recipe.create(recipe_params)
@recipes = Recipe.all
end
def edit
@recipe = Recipe.find(params[:id])
end
def update
@recipe = Recipe.find(params[:id])
@recipe.update(recipe_params)
redirect_to root_path
end
def destroy
recipe = Recipe.find(params[:id])
recipe.destroy
redirect_to root_path
end
private
def recipe_params
params.require(:recipe).permit(:dish_name, :cook_method)
end
編集モーダルを表示したいページに以下を記述
<div id="product-modal" class="modal fade" tabindex="-1" role="dialog" aria-hidden="true"></div>
編集モーダルへのlink_toにはremote: trueを追加する
<div class="offset-1 pb-2">
<%= link_to '編集', edit_recipe_path(recipe.id), method: :get, class: "btn btn-secondary btn-sm", remote: true %>
<%= link_to '削除', recipe_path(recipe.id), method: :delete, class: "btn btn-secondary btn-sm", data:{confirm: 'Are you sure?'} %>
</div>
モーダルの作成
editアクションが呼び出された際にモーダルを出したいので部分テンプレートとして作成
非同期にしたいのでform_withのlocalオプションはfalseに変更
<div class="modal-dialog">
<div class="modal-content">
<%= form_with model: @recipe, local: false do |f| %>
<div class="modal-body">
<div class="form-group">
<%= f.label :dish_name, "レシピ" %>
<%= f.text_field :dish_name, class: "form-control" %>
</div>
<div class="form-group">
<%= f.label :cook_method, "作り方" %>
<%= f.text_area :cook_method, class: "form-control" %>
</div>
</div>
<div class="modal-footer">
<%= f.submit "編集する", class: "btn btn-primary" %>
<% end %>
</div>
</div>
</div>
editアクションと連動するためにeditページを二つ作成
編集ページを非同期でモーダル表示したいのでeditページの拡張子はjs.erbにする
formのlink_toでremoteをつけることでedit.js.erbが読み込まれモーダルウインドウを表示させる
product-modalのidを取得し、escape_javascriptで下記の_edit.html.erbにエスケープ処理
showメソッドでモーダルの表示
$("#product-modal").html("<%= escape_javascript(render 'edit') %>")
$("#product-modal").modal("show")
モーダルフォームにレンダリング
<%= render partial: 'modal' %>
updateアクションと連動するためのファイル作成
下記の_save.js.erbへのレンダリング
<%= render 'save' %>
escape_javascriptでindex.html.erbにエスケープ処理
hideメソッドでモーダルを非表示にする
$().html("<%= escape_javascript(render 'index') %>")
$("#product-modal").modal("hide")
以上が実装した手順
Bootstrap5自体にJQueryが不要なので他の方法がありそう
$().html("<%= escape_javascript(render 'index') %>")にクラスを指定しなくても動いたり投稿用のモーダルに若干の不具合が発生したりしたので修正の必要があるので解決次第、記事を更新する