0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Ajaxで非同期削除をしてみる

Last updated at Posted at 2023-04-06

view

  • Ajaxでタスクを削除するための作戦

⑴削除はサーバサイドでやる必要があるものの、今表示している一覧画面をそのまま表示し続けていたいため、Ajaxでサーバにリクエストを飛ばす

⑵削除された項目の非表示は、クライアントサイドにてJavaScriptで行う。
 ’⑴’の処理が無事行われたら非表示になるようにする

  • ページ遷移ではなくAjaxリクエストを発生させる
    remote: trueを記述
index.html.slim
= link_to '', user, method: :delete, remote: true, data: { confirm: "ユーザ「#{user.name}」を削除します。よろしいですか?" }, class: 'far fa-trash-alt fa-lg'

controller

  • destroyアクションをAjax向けに変更する
    具体的には、リダイレクトをなくし、ステータスコード(204)だけ返すようにする。
    ※HTTP のレスポンスコード 204 No Content は、リクエストが成功した事を示します
user_controller.rb
def destroy
  @user.destroy
  head :no_content
  # redirect_to users_url, notice: "ユーザ「#{@user.name}」を削除しました"
end

RailsのHTTPステータスのシンボル表現まとめ
https://blog.toshimaru.net/rails-http-status-symbols/

javaScript

[記載場所]

  • 通常(v6.0のデフォルトはWebpackerになっている)
    app/javascript/packs 配下のファイル
    app/assets/javascripts/xxxxx.js

RailsGuide(v6.0)
https://railsguides.jp/asset_pipeline.html
※アセットパイプラインはassetsフォルダ内の各ファイルを最終的に一つのファイルに連結・圧縮する)
アセットパイプラインのパスを変える場合は、config/initializers/assets.rb内を変更する

  • 組み込みrubyを使う場合
    app/views/[controller名]/xxxxx.js.erb
    ※js.erbファイルでないと、<%= user.name %>などの記述は読み込めない

  • Webpackerを使う
    app/javascript/packs配下
    ※Webpackerでバンドルされたファイルは public/packs 配下にコピーされる。
    (バンドルする対象のファイルは app/javascript 配下のファイル)

バンドルする単位をエントリーポイントと呼び、エントリーポイントとなるファイルは app/javascript/packs 配下のファイルです。
CSS,javaScript のどちらも app/javascript/packs 配下に配置することでエントリーポイントとすることが出来る。
※エントリーポイントとなるファイルに javaScript は import, CSS は @import を記載ればそれらがエントリーポイントのファイル名としてバンドルされる。

  • 削除した対象を非表示にする

Ajaxは非同期通信です。
そのため、削除が成功したことを確認してから非表示にするためには、「削除処理が成功した」というイベントのハンドラの中に、対象を非表示にする処理を記述します。

rails-ujsは、remote: trueをつけたa要素に対して、Ajax通信が成功した時に、ajax:successというイベントを発行してくれます。
そこで、これに対応するイベントハンドラを記述します。

イベントハンドラを追加するにあたっては、対象となるa要素を簡単に特定できるようにしたいので、まずは、次のように削除リンクのa要素に「delete」という独自のCSSクラスを目印として付与してみます。

index.html.slim
= link_to '', user, method: :delete, remote: true, data: { confirm: "ユーザ「#{user.name}」を削除します。よろしいですか?" }, class: 'far fa-trash-alt fa-lg delete'
  • この目印を利用して、削除リンク(a要素)にイベントハンドラを設定します。
    ※ここでは、Turbolinksを利用しているため、windows.onloadを利用していない
app/assets/javascripts/user.js
document.addEventListener('turbolinks:load', function() {

  document.querySelectorAll('.delete').forEach(function (a) {
    a.addEventListener('ajax:success', function() {
      var td = a.parentNode;
      var tr = td.parentNode;
      tr.style.display = 'none';
    });
  })

});
  • 確認方法

・javaScriptのDOM要素はデベロッパーツールのコンソールでタグを堀々して確認してから実装しましょう。非表示対象を見つけたら、style.display = 'none' にしてみましょう。

・javaScriptが正常動作しない場合は、
デベロッパーツールのブレークポイントでどこまでコードを読めているか?を見ましょう。

・Ajax通信についても、通信が正常にできているかはデベロッパーツールで確認する事ができます。
期待するNetworkXHRでステータスが返ってきているかを見ましょう

・フロントエンドだけでなくバックエンドまで確認しましょう。
うまくいかない場合は、登場人物を明確にしてデータの受け渡しフローのどこでつまづいているのか?を切り分けましょう。

備考

techRacho
Rails 6: Webpacker+Yarn+Sprocketsを十分理解してJavaScriptを書く: 前編(翻訳)
https://techracho.bpsinc.jp/hachi8833/2020_01_16/85940

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?