はじめに
RailsのAjaxを使って特定の要素を編集・更新する方法について記載します。
例で簡単なカテゴリー一覧画面の1つのカテゴリーの名前を更新する処理を使います。
バージョン
- ruby 2.6.3
- rails 5.2.1
画面概要
この右のほうにある鉛筆マークの編集アイコンボタンを押すと、該当の行のカテゴリー名がフォームに変わります。
変更後のカテゴリー名にデータが更新され、表示を非同期で変更します。
例では、「交通」→「交通費」に変更します。
処理概要
-
要素にAjaxのためのオプションを追加
link_toにremote: true
オプションをつけます。 -
Ajaxするためのルーティングを追加
-
コントローラやモデルでオブジェクトの取得または更新
-
追加したアクションのためのJavaScript用のviewファイルを用意し、画面の該当の要素を変更するためのJavaScriptを記載
実装前
実装前の主要なコード部分は以下になります。
def index
@categories = Category.where(user: current_user).order(:created_at)
end
<ul class="todo-list" id="own-categories">
<% @categories.each do |category| %>
<li id="category-list-id-<%= category.id %>">
<%= render 'a_category_list', category: category %>
</li>
<% end %>
</ul>
<span class="handle ui-sortable-handle">
<i class="fa fa-ellipsis-v"></i>
<i class="fa fa-ellipsis-v"></i>
</span>
<span class="text"><%= category.name %></span>
<%= category.common_mark %>
<div class="tools">
<%= link_to edit_category_path(category), class: "text-redpepper space-left" do %>
<i class="fa fa-lg fa-edit"></i>
<% end %>
<%= category.common_btn %>
</div>
カテゴリー名を編集するフォームに変更するAjax処理の実装
鉛筆マークの編集アイコンボタンを押下して、カテゴリー名の要素をフォーム要素に変更する処理を記載していきます。
※注意:説明しないclass属性やid属性などがありますが、Ajax処理とは関係ありません。
1. Ajaxするためのオプションを追加
編集アイコンボタンにremote: trueを仕込む。
<%= link_to edit_category_path(category), remote: true, class: "text-redpepper space-left" do %>
<i class="fa fa-lg fa-edit"></i>
<% end %>
2. Ajaxするためのルーティングを追加
Ajaxするときでも、ルーティングのresourcesメソッドが柔軟に対応してくれます。
ここでは、editアクションを追加します。
resources :categories, only: [:index, :edit]
3. コントローラでオブジェクトの取得
def edit
@category = Category.find(params[:id])
end
4. 追加したアクションのためのJavaScript用のviewファイルを用意し、画面の該当の要素を変更するためのJavaScriptを記載
editアクションなので、app/views/categories/edit.js.erb
を作成します。
id = "<%= @category.id %>";
target = document.querySelector(`#category-list-id-${id}`);
html = "<%= j(render partial: 'form', locals: { category: @category }) %>";
target.innerHTML = html;
<%= form_with(model: category) do |form| %>
<div class="row">
<div class="col-xs-10">
<div class="input-group input-group-sm">
<%= form.text_field :name, value: category.name, required: true, class:"form-control", max: 15 %>
<span class="input-group-btn">
<%= form.submit submit_btn_letters, class: "btn btn-brown" %>
</span>
</div>
</div>
<div class="col-xs-1">
<%= category.cancel_btn %>
</div>
</div>
<% end %>
これで、カテゴリー名を編集するためのフォームが表示できます。
カテゴリー名を更新するAjax処理の実装
編集フォームに変更できたので、次に、変更したい文字「交通費」に変更して、
更新ボタンを押下し、更新後のカテゴリー名を表示する処理を記載していきます。
1. Ajaxするためのオプションを追加
form_withにremote: true
オプションを追加します。
(明示的に記載しなくてもデフォルトでremote: trueにはなっている。)
<%= form_with(model: category, remote: true) do |form| %>
<!-- 省略 -->
<% end %>
2. Ajaxするためのルーティングを追加
updateアクションを追加
resources :categories, only[:index, :edit, :update]
3. コントローラでオブジェクトの更新
カテゴリー名を「交通費」で更新します。
def update
@category = Category.find(params[:id])
@category.update(category_params)
end
private
def category_params
params.require(:category).permit(:name, :is_common)
end
4. 追加したアクションのためのJavaScript用のviewファイルを用意し、画面の該当の要素を変更するためのJavaScriptを記載
編集フォームを更新したカテゴリー名に変更する処理を行います。
updateアクションなのでapp/views/categories/update.js.erb
を作成します。
id = "<%= @category.id %>";
target = document.querySelector(`#category-list-id-${id}`);
html = "<%= j(render partial: 'categories/a_category_list', locals: { category: @category }) %>";
target.innerHTML = html;
おわりに
JavaScriptでAjax処理を書いてもいいのですが、シンプルなAjaxはRailsであれば簡単にできます。
ただ、〇〇.js.erb
の書き方は癖が強いので要注意です。