0
0

More than 1 year has passed since last update.

[Rails]DELETEリンクでpreventDefaultが効かない

Last updated at Posted at 2021-12-04

環境

ruby 2.6.5
Rails 6.0.4.1
sweetalert2(CDN)

実装したい機能

削除ボタンを押すと、ブラウザに警告アラートを出す。
OKを押すと削除され、Cancelを押すと、元の画面に戻る。

イメージ↓
cation.png

実装方法

削除リンク要素をgetElementByIdで取得。
クリックイベント内でpreventDefaultを使用し、削除イベントを中止。
sweetalert2を使用して、警告アラートを表示。
OKが押された場合のみ、削除処理を進める。

生じた問題

Railsのヘルパーメソッドであるlink_toで削除リンクを実装した場合、
JavascriptのpreventDefaultメソッドが効かず、
コントローラー処理が呼び出されてしまう。
解決策へ飛ぶ

原因特定までの経緯

JSにdebugger、Railsコントローラー側にbinding.pryを記述し動かすと、
binding.pryも発動した。
コントローラーにリクエストが届いてしまっている。
つまり、イベントがキャンセルできていないと考えた。

ビューファイル抜粋

<td>
  <%= link_to '削除', user_xxx_path(@user, xxx), method: :delete, id: "test" %>
</td>

コントローラー処理抜粋

  def destroy
    binding.pry
    @xxx = Xxx.find_by(id: params[:id])    
    redirect_to user_path(current_user) if @xxx.destroy
  end

JSファイル

function cation() {
  //削除要素の取得
  const test = document.getElementById("test");
  // 削除ボタン押下でイベント発火
  test.addEventListener('click',(e) => {
    console.log("イベント読み込みok");
    console.log(e.cancelable);
    e.preventDefault();
    debugger;

  // 削除警告画面
    Swal.fire({
      title: '◯◯◯を削除します',
      html: '過去の△△△も削除され、元に戻せません。',
      footer: '<a href="#" class="text-blue-400 hover:bg-gray-200">◯◯◯の解約はこちら</a>',
      icon: 'warning',
      showCancelButton: true,
      confirmButtonColor: '#3085d6',
      cancelButtonColor: '#d33',
      confirmButtonText: 'OK',
      allowOutsideClick: false,
    }).then((result) => {
      if (result.isConfirmed) {
        Swal.fire(
          '削除しました',
          'Your file has been deleted.',
          'success'
        )};
    });
  });
};

window.addEventListener('load', cation);

また、下記についても確認がとれた。

・要素選択、イベント発火に問題はない
→console.log("イベント読み込みok")で、イベントの読み込みは確認できた。

・ aタグのリンク遷移はキャンセル可能なイベントである
→console.log(e.cancelable)の結果がtrueであった。

以上から、ヘルパーメソッド(link_to)に
オプションでメソッド(method: :delete)を指定しているのが
原因ではないかと考えた。

それを検証するために、メソッドオプションを指定しない編集リンクを作成した。

追加検証:ビュー抜粋

<%# ↓編集リンク追加 %>
<td>
  <%= 編集', edit_user_subscription_path(@user, subs), id: "test-b", %>
</td>
<%# ↑編集リンク追加 %>
<td>
  <%= link_to '削除', user_xxx_path(@user, xxx), method: :delete, id: "test" %>
</td>

追加検証:該当コントローラー

  def edit
    binding.pry
    @xxx = Xxx.find_by(id: params[:id])    
  end

JSファイル
要素をtestからtest-bに変更

function cation() {
  //削除要素の取得
  const test-b = document.getElementById("test-b");
  // 削除ボタン押下でイベント発火
  test-b.addEventListener('click',(e) => {
    console.log("イベント読み込みok");
    console.log(e.cancelable);
    e.preventDefault();
    debugger;
    ~以下、略〜

これで編集リンクをクリックすると、
debuggerのみ動作し、binding.pryは動作しなかった。
コントローラーが動いていないことから、イベントが中止できたと判断した。

念の為、削除要素の(method: :delete)を消して同様のテストをしたところ、
編集リンクと同様の挙動となった。

つまり、ヘルパーメソッド(link_to)のオプション、
メソッドの指定(method: :delete)が原因だと特定できた。

また、ヘルパーメソッドを使用せずaタグで試したが同様の結果であった。

<a id="test-b" data-method="delete" href=<%= user_subscription_path(@user, xxx) %> >削除</a>

解決策

formを作り、a要素をinput要素(submit)に変更。
コントローラーのbinding.pryが動作せず、
JS側のdebuggerのみ動作することを確認。
無事イベントを中止にできた。

<%= form_with url: user_xxx_path(@user, xxx), method: :delete, local: true do |f| %>
  <%= f.submit '削除', id: "test" %>
<% end %>

かなり古い2次情報記事だが、こちらを参考に上記方法を検証した。
teratail

感想

MDN(addEventListener, preventDefault, a)、
Railsドキュメント(link_to)等を確認し、
オプションなどを試してみたがうまく行かなった。

また、そもそも一次情報に書かれいていることをを理解できなかった。

問題が解決できたこと、
またその結果実装を進められる結果は、良いが、
解決方法とそこまでの過程が課題アリだなと感じた。

具体的には、「イベントオブジェクト」について理解を深める必要がある。
簡易アクションとして、MDNでイベント入門を確認。
アプリ実装後、もっと詳しく見ていきたい。

***
オリアプ実装していると、「ちゃんと理解できていない」がよくわかる。
カリキュラム学習では、わかった!と思い、
課題実装でスムーズに実装できていても、
「自由に使いこなす」には至らないことを痛感する。

もっと理解したいポジティブな感情と同時に、
今、自力で答えを見つけられないくやしやだったり、
実装を優先するため、一時保留にする不安や焦りもわいてくる。

後者は、ネガティブな感情ではあるが、
何かに取り組み、対峙している結果とも捉えられる。

まだスタートラインにも立ってないし、
課題も改善も山積みだが、
今は、取り組み続けることにフォーカスしようと思った。

まずは、オリアプを完成させる!

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