LoginSignup
4
2

More than 3 years have passed since last update.

【Ruby on Rails】Ajaxで特定の要素を変更する

Last updated at Posted at 2020-03-28

はじめに

RailsのAjaxを使って特定の要素を編集・更新する方法について記載します。
例で簡単なカテゴリー一覧画面の1つのカテゴリーの名前を更新する処理を使います。

バージョン

  • ruby 2.6.3
  • rails 5.2.1

画面概要

以下のような画面です。
スクリーンショット 2020-03-28 22.13.26.png

この右のほうにある鉛筆マークの編集アイコンボタンを押すと、該当の行のカテゴリー名がフォームに変わります。
スクリーンショット 2020-03-28 19.32.07.png

カテゴリー名を変更し、「更新」を押すと、
スクリーンショット 2020-03-28 19.33.11.png

変更後のカテゴリー名にデータが更新され、表示を非同期で変更します。
例では、「交通」→「交通費」に変更します。
スクリーンショット 2020-03-28 22.13.58.png

処理概要

  1. 要素にAjaxのためのオプションを追加
    link_toにremote: trueオプションをつけます。

  2. Ajaxするためのルーティングを追加

  3. コントローラやモデルでオブジェクトの取得または更新

  4. 追加したアクションのためのJavaScript用のviewファイルを用意し、画面の該当の要素を変更するためのJavaScriptを記載

実装前

実装前の主要なコード部分は以下になります。

app/controllers/categories_controller.rb
def index
  @categories = Category.where(user: current_user).order(:created_at)
end
app/views/categories/index.html.erb
<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>
app/views/categories/_a_category_list.html.erb
<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を仕込む。

app/views/categories/_a_category_list.html.erb
<%= 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アクションを追加します。

config/routes.rb
resources :categories, only: [:index, :edit]

3. コントローラでオブジェクトの取得

app/controllers/categories_controller.rb
def edit
  @category = Category.find(params[:id])
end

4. 追加したアクションのためのJavaScript用のviewファイルを用意し、画面の該当の要素を変更するためのJavaScriptを記載

editアクションなので、app/views/categories/edit.js.erbを作成します。

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;
app/views/categories/_form.html.erb
<%= 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 %>

これで、カテゴリー名を編集するためのフォームが表示できます。
スクリーンショット 2020-03-28 19.32.07.png

カテゴリー名を更新するAjax処理の実装

編集フォームに変更できたので、次に、変更したい文字「交通費」に変更して、
更新ボタンを押下し、更新後のカテゴリー名を表示する処理を記載していきます。

1. Ajaxするためのオプションを追加

form_withにremote: trueオプションを追加します。
(明示的に記載しなくてもデフォルトでremote: trueにはなっている。)

app/views/categories/_form.html.erb
<%= form_with(model: category, remote: true) do |form| %>
  <!-- 省略 -->
<% end %>

2. Ajaxするためのルーティングを追加

updateアクションを追加

config/routes.rb
resources :categories, only[:index, :edit, :update]

3. コントローラでオブジェクトの更新

カテゴリー名を「交通費」で更新します。

app/controllers/categories_controller.rb
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を作成します。

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;

以上で、カテゴリー名を非同期で更新することができました。
スクリーンショット 2020-03-28 22.13.58.png

おわりに

JavaScriptでAjax処理を書いてもいいのですが、シンプルなAjaxはRailsであれば簡単にできます。
ただ、〇〇.js.erbの書き方は癖が強いので要注意です。

4
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
2